Part1:SpringBoot原理(本质上就是Spring,通过自己的特性帮我们简化了Spring的开发(或者说帮我们简化了ssm下的配置文件))三个核心特性(要是面试等让谈一下springboot的理解,就从自动装配和run()方法两个方面谈
)----【SpringBoot的run()方法启动源码解析](链接:https://pan.baidu.com/s/1qGjL_APK1yap4SrhQudA-Q 提取码:1234 。或者https://github.com/AIminminAI/MindMaps/blob/main/SpringBoot%E7%9A%84run%E6%96%B9%E6%B3%95%E5%90%AF%E5%8A%A8%E6%BA%90%E7%A0%81_new.png】
- springboot所有的自动配置都
在启动类中启动的时候被扫描并加载
,加载进来其实指的就是扫描了一个META-INF下的spring.factories(所有的自动配置类都在这里面)
。
- 但是不一定被扫面进来的都生效,生不生效要看条件@ConditionalOnXxx里面的条件是否成立,只要导入了对应的start(中的坐标)就有对应的启动器了,有了启动器对应的自动装配就会生效,然后就配置成功了
//通过@SpringBootApplication这个写在类上的注解开启组件扫描和自动配置。标记这个类是一个springboot应用 //@SpringBootApplication(呼应到SSM中)是SSM中三个注解的结合体 @SpringBootApplication public class XXXXXApplication { public static void main(String[] args) { //通过SpringApplication.run(......)引导应用程序启动,**启动run()方法相当于开启了一个服务** SpringApplication.run(XXXXXApplication.class, args);//:run()方法有两个参数,命令行参数以及当前这个类 } }
- 跟着源码一步一步debug,看源码之前看注释。刚开始肯定是主程序类呗,其实就是实例化一个SpringApplication出来拿着这个去搞事情,那实例化dubug后知道调用的是SpringApplication的有参构造器,在这个构造器中进行了很多参数赋值设置,然后对当前应用程序类型做一个判断 。
spring.factories只在俩jar包中有,而spring.factories中有很多配置类,以key=value形式存在
。
- SpringFactoriesLoader.java中的loadFactoryNames方法中的loadSpringFactories方法,在loadSpringFactories方法中利用ClassLoader.getResources(“变量路径最终指到META-INF/spring.factories”)以及ClassPath.getSystemResources(“”),去当前路径的ClassPath下面查找配置信息,然后以Enum的形式【Enumeration urls = …】存着给后面用。【你后面咋用呢,不就是@ConditionalOnXxx,@Enable…,还有prefix = …不都是在玩这些个配置信息嘛】。然后对urls进行迭代遍历,取出其中的配置信息,也就是spring.factories中key=value中的value。
- 这里用到了缓存的思想,为了提升后面配置信息的加载速度,SpringBoot会提前cache.put(classLoader, result)【这个result是个LinkedMultiValueMap<>()】,就不需要哼哧哼哧再去spring.factories用到再取用到再取,麻烦。
- 取出value对应的类后就需要利用反射创建对象了,ClassUtils.forName(…),然后getDeclareConstructor、实例化…,然后就有了一个装着实例的List了呗,用从里面拿就行。
- 跟着源码一步一步debug,看源码之前看注释。刚开始肯定是主程序类呗,其实就是实例化一个SpringApplication出来拿着这个去搞事情,那实例化dubug后知道调用的是SpringApplication的有参构造器,在这个构造器中进行了很多参数赋值设置,然后对当前应用程序类型做一个判断 。
autoconfig.jar的spring.factories配置文件中有很多XxxAutoConfiguration类,这些类就是来帮助我们完成自动装配的。咱们需要哪个组件,就把哪个组件在pom.xml中写上加进来就行了。但是autoconfig.jar的spring.factories配置文件中有很多XxxAutoConfiguration类真的很多,咱们不可能每次启动程序时把这些都加载进来吧,所以出现了@ConditionalOnXxx这个注解,就是来帮咱们做排除法的
- 但是不一定被扫面进来的都生效,生不生效要看条件@ConditionalOnXxx里面的条件是否成立,只要导入了对应的start(中的坐标)就有对应的启动器了,有了启动器对应的自动装配就会生效,然后就配置成功了
- SpringBoot的run()方法启动源码解析](链接:https://pan.baidu.com/s/1qGjL_APK1yap4SrhQudA-Q 提取码:1234
- 或者看这里:https://github.com/AIminminAI/MindMaps/blob/main/SpringBoot%E7%9A%84run%E6%96%B9%E6%B3%95%E5%90%AF%E5%8A%A8%E6%BA%90%E7%A0%81_new.png
- Part1-0.自动配置(SpringBoot的自动配置是一个运行时(应用程序启动时)的过程,SpringBoot会考虑很多因素从而决定用哪个),启动流程。或者说,
SpringBoot的自动配置就是通过注解或者一些简单的配置就能在 Spring Boot 的帮助下实现某块功能
- 自动配置原理相关的简陋版源码解析:
- https://gitee.com/aiminminai/mind-mapping
- https://github.com/AIminminAI/MindMaps
- 再复习一下注解:注解其实就是四个元注解+ public @interface xxx(){}的一个类
- @Target:描述注解的使用范围,也就是注解能用在什么地方,类上、接口上、成员变量上
- @Retention:指定注解在SOURCE<CLASS<RUNTIME三个阶段中的什么时候生效
- @Document:说明这个注解将被包含在javadoc中
- @inherited:说明子类可以继承父类中的该注解
- 实际上Spring Framework已经实现了这个自动配置功能,SpringBoot只是在Spring Framework的基础上通过SPI的方式作了进一步的优化。
- 总的来说【
SpringBoot 定义了一套接口规范,这套规范规定:SpringBoot 在启动时会扫描外部引用 jar 包中的META-INF/spring.factories文件,将文件中配置的类型信息加载到 Spring 容器,并执行类中定义的各种操作。对于外部 jar 来说,只需要按照 SpringBoot 定义的标准,就能将自己的功能装置进 SpringBoot
。】,这套规范就是SPI - 或者说,
java SPI
,这个东西其实就是一种动态替换发现的机制,比如有个接口,java.sql.Driver接口,人家不同厂商可以针对这个同一个接口做出不同的实现,经常见得实现有mysql、postgresql等,将这些不同的实现提供给用户,而java的SPI机制就是为某个接口寻找服务的子实现的
。他这个有个缺点就是会全部扫描,所以Dubbo中实现了自己的SPI机制,可以按需加载子实现。
- 总的来说【
- 自动配置原理相关的简陋版源码解析:
- 自动配置的原理可以从两个角度去看:
- 第一个角度是:从注解的源码出发,一层一层看注解们是如何起作用的:自动装配原理中东西如下:【https://gitee.com/aiminminai/mind-mapping、https://github.com/AIminminAI/MindMaps】
- 1.容器在启动的时候会调用@SpringBootApplication注解,这个核心注解里面包含了三个注解【@SpringBootConfiguration(底层还是@Configuration注解喽)、@EnableAutoConfiguration、@ComponentScan】
- @SpringBootApplication看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。
- @ComponentScan:@SpringBootApplication中的@ComponentScan用来扫描被@Component (@Repository,@Service,@Controller)注解的 bean,注解默认会扫描该类所在的包下所有的类。
- 可以自定义不扫描某些 bean。比如,容器中将排除TypeExcludeFilter和AutoConfigurationExcludeFilter
- 可以自定义不扫描某些 bean。比如,容器中将排除TypeExcludeFilter和AutoConfigurationExcludeFilter
@SpringBootConfiguration
:组合了或者说底层就是 @Configuration 注解,实现配置文件的功能【你点进@SpringBootConfiguration的源码,里面其实就是@Configuration】。表示这个被@SpringBootConfiguration注解的类是一个配置类,这个类里面是可以直接写bean的。@bean...
- @Configuration:允许在 Spring 上下文中注册额外的 bean 或导入其他配置类
- @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制。@SpringBootApplication中
@EnableAutoConfiguration的底层包含@AutoConfigurationPackage和@Import注解两部分。@Import注解用来导入一些会被Spring创建并加载到IOC容器中的配置类,也就是动态启动或者说某些功能【打开自动配置的功能,也可以关闭某个自动配置的选项**,如**关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })**】,实际上@Import注解就加载导入了一个AutoConfigurationImportSelector.class ,然后调用这个类的的 selectImports方法获取一个全面的常用 BeanConfiguration 列表
。【打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
。】
- AutoConfigurationImportSelector.class【
EnableAutoConfiguration 只是一个简单地注解,自动装配核心功能的实现实际是通过 AutoConfigurationImportSelector类
。】:点进这个AutoConfigurationImportSelector.class就可以看到下面几部分:
AutoConfigurationImportSelector.class类的具体继承情况,也可以看到selectImports方法的由来【AutoConfigurationImportSelector 类实现了 ImportSelector接口,也就实现了这个接口中的 selectImports方法。selectImports方法主要用于获取所有符合条件的类的全限定类名,这些所有符合条件的类的全限定类名对应的类需要被加载到 IoC 容器中
。】:
private static final String[] NO_IMPORTS = new String[0]; public String[] selectImports(AnnotationMetadata annotationMetadata) { // <1>.判断自动装配开关是否打开 if (!this.isEnabled(annotationMetadata)) { return NO_IMPORTS; } else { //<2>.获取所有需要装配的bean AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader.loadMetadata(this.beanClassLoader); AutoConfigurationImportSelector.AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata); return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); } }
- protected AutoConfigurationEntry getAutoConfigurationEntry( …){…}:
getAutoConfigurationEntry()方法主要负责加载自动配置类的
。
- 第 1 步:判断自动装配开关是否打开。默认spring.boot.enableautoconfiguration=true,可在 application.properties 或 application.yml 中设置
- 第 2 步 :用于获取EnableAutoConfiguration注解中的 exclude 和 excludeName。
- 第 3 步:
获取需要自动装配的所有配置类,读取META-INF/spring.factories
:spring-boot/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
- 这个文件的配置内容都被我们读取到了。XXXAutoConfiguration的作用就是按需加载组件。不光是这个依赖下的META-INF/spring.factories被读取到,
所有 Spring Boot Starter 下的META-INF/spring.factories都会被读取到
。
- 第 4 步 :debug 到后面发现configurations 的值变小了。说明“spring.factories中这么多配置,
不是每次启动都要全部加载
。因为,这一步有经历了一遍筛选,@ConditionalOnXXX 中的所有条件都满足,该类才会生效
。@Configuration // 检查相关的类:RabbitTemplate 和 Channel是否存在 // 存在才会加载 @ConditionalOnClass({ RabbitTemplate.class, Channel.class }) @EnableConfigurationProperties(RabbitProperties.class) @Import(RabbitAnnotationDrivenConfiguration.class) public class RabbitAutoConfiguration { }
- 第 1 步:判断自动装配开关是否打开。默认spring.boot.enableautoconfiguration=true,可在 application.properties 或 application.yml 中设置
- public static List loadFactoryNames(…){…}:里面主要的代码逻辑是获取了项目资源配置信息:
- AutoConfigurationImportSelector.class【
- @ComponentScan:@SpringBootApplication中的@ComponentScan用来扫描被@Component (@Repository,@Service,@Controller)注解的 bean,注解默认会扫描该类所在的包下所有的类。
- @SpringBootApplication看作是 @Configuration、@EnableAutoConfiguration、@ComponentScan 注解的集合。
- 2.之后会读取
spring-boot-autoconfigure.jar 下面的spring.factories
,获取到所有的 Spring 相关的 Bean 的全限定名 ClassName
这里面的“META-INF/spring.factories:从这里获取项目资源配置信息”涵盖了很多点,如下:
首先,就是这个前面文章说过的核心注解:@ConditionalOnXXX:会去判断一下要是这里面的条件都成立才会生效
代表你没有配置时我才给你
SpringBoot是如何知道要创建哪个Bean的?比如SpringBoot是如何知道要创RedisTemplate的?咱们学了启动器后知道是咱们导入了redis的start启动依赖,然后springboot就帮咱们创建了RedisTemplate。如果我不导入这个redis的start启动依赖,springboot会不会帮咱们创建了RedisTemplate,springboot怎么知道导没导这些启动依赖呢
其次,就是咱们从**spring.factories(spring.factories底下的配置类都是XXXAutoConfiguration)**中挑一句举个例子:org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,
- 再比如,切换内置Web服务器:
- 由于有自动配置类中的@ConditionalOnXxx注解存在,我们只需要导入不同的web服务器的坐标,就可以实现服务器的动态切换。比如排除tomcat引入netty
- 由于有自动配置类中的@ConditionalOnXxx注解存在,我们只需要导入不同的web服务器的坐标,就可以实现服务器的动态切换。比如排除tomcat引入netty
- 再比如,切换内置Web服务器:
- 3.之后继续调用 filter 来一一筛选,也就是并不是所有的Bean都会被初始化,在配置类中使用Condition来加载满足条件的Bean,过滤掉一些我们不需要不符合条件的 Bean
- 4.最后把符合条件的 BeanConfiguration 注入默认的 EnableConfigurationPropertie 类里面的属性值,并且注入到 IOC 环境当中
- 第二个角度是:从src/main/java/XXXXXApplication.java(主入口,不能删不能改。springboot启动类就是Spring的一个Component组件,更何况以他为基础而启动的springboot中的诸多东西呢):应用程序启动类,起配置和引导的作用的角度出发
//通过@SpringBootApplication这个写在类上的注解开启组件扫描和自动配置,标记这个类是一个springboot应用 @SpringBootApplication public class XXXXXApplication { public static void main(String[] args) { //通过SpringApplication.run(......)引导应用程序启动 SpringApplication.run(XXXXXApplication.class, args); } }
里面的SpringApplication.run(XXXXXApplication.class, args);方法如下:
- SpringApplication.run():SpringBoot的run()方法启动源码解析](链接:https://pan.baidu.com/s/1qGjL_APK1yap4SrhQudA-Q 提取码:1234
SpringApplication就是事件源对象,将来所有的事件都是在这个对象上产生的。先实例化也就是初始化这个SpringApplication这个类,然后调用他的run方法
第一行传入的primarySources就是我们需要运行的函数的入口类或者叫启动类或者叫引导类
下面阴影部分就是判断是不是web环境,
为null说明不是web环境,然后接着执行,从SpringFactories中加载监听器和Initializers
初始化或者说实例化完之后,就要调用run方法了【SpringBoot的run()方法启动源码解析](链接:https://pan.baidu.com/s/1qGjL_APK1yap4SrhQudA-Q 提取码:1234 】
stopWatch是个定时器,就可以看出项目运行所需时间,不是有个start和end嘛
- SpringApplication.run():SpringBoot的run()方法启动源码解析](链接:https://pan.baidu.com/s/1qGjL_APK1yap4SrhQudA-Q 提取码:1234
- 1.容器在启动的时候会调用@SpringBootApplication注解,这个核心注解里面包含了三个注解【@SpringBootConfiguration(底层还是@Configuration注解喽)、@EnableAutoConfiguration、@ComponentScan】
- 第一个角度是:从注解的源码出发,一层一层看注解们是如何起作用的:自动装配原理中东西如下:【https://gitee.com/aiminminai/mind-mapping、https://github.com/AIminminAI/MindMaps】
- Part1-1:run()方法启动过程,用SpringApplication.run(StartupApplication.class, args);为开始进行探究
- 【SpringBoot的run()方法启动源码解析](链接:https://pan.baidu.com/s/1qGjL_APK1yap4SrhQudA-Q 提取码:1234 】
- https://gitee.com/aiminminai/mind-mapping
- https://github.com/AIminminAI/MindMaps
- 【SpringBoot的run()方法启动源码解析](链接:https://pan.baidu.com/s/1qGjL_APK1yap4SrhQudA-Q 提取码:1234 】
- Part1-2.起步依赖
常用的官方起步依赖:
<dependencies>
<!--SpringBoot整合Web功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--SpringBoot整合Actuator功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--SpringBoot整合AOP功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--SpringBoot整合测试功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--SpringBoot整合注解处理功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--SpringBoot整合Spring Security安全功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--SpringBoot整合Redis数据存储功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--SpringBoot整合Elasticsearch数据存储功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!--SpringBoot整合MongoDB数据存储功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!--SpringBoot整合AMQP消息队列功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!--SpringBoot整合Quartz定时任务功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
<!--SpringBoot整合JPA数据存储功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--SpringBoot整合邮件发送功能依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
</dependencies>
第三方起步依赖:
<dependencies>
<!--SpringBoot整合MyBatis数据存储功能依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-version.version}</version>
</dependency>
<!--SpringBoot整合PageHelper分页功能依赖-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper-starter.version}</version>
</dependency>
<!--SpringBoot整合Druid数据库连接池功能依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!--SpringBoot整合Springfox的Swagger API文档功能依赖-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox-version}</version>
</dependency>
<!--SpringBoot整合MyBatis-Plus数据存储功能依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus-version}</version>
</dependency>
<!--SpringBoot整合Knife4j API文档功能依赖-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j-version}</version>
</dependency>
</dependencies>
比如要使用Mysql数据库进行存储,用Swagger生成API文档,添加如下起步依赖即可
<dependencies>
<!--SpringBoot Web功能起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--MyBatis分页插件-->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.10</version>
</dependency>
<!--集成druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--Mysql数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<!--springfox swagger官方Starter-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
</dependencies>
也可以用Maven的方式来排除不想要的依赖。比如不想使用tomcat容器、想使用undertow容器
<dependencies>
<!--SpringBoot Web功能起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<!--排除tomcat依赖-->
<exclusion>
<artifactId>spring-boot-starter-tomcat</artifactId>
<groupId>org.springframework.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--undertow容器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
</dependencies>
- SpringBoot 项目的 spring-boot-starter-web 依赖中已经有 hibernate-validator 包【更新版本的 spring-boot-starter-web 依赖中不再有 hibernate-validator 包(如2.3.11.RELEASE),需要自己引入 spring-boot-starter-validation 依赖。】,不需要引用相关依赖。可以通过 idea 插件—Maven Helper 生成:
- 数据的校验的重要性就不用说了,
即使在前端对数据进行校验的情况下,我们还是要对传入后端的数据再进行一遍校验,避免用户绕过浏览器直接通过一些 HTTP 工具直接向后端请求一些违法数据
。JSR(Java Specification Requests) 是一套 JavaBean 参数校验的标准
,它定义了很多常用的校验注解【所有的注解,推荐使用 JSR 注解,即javax.validation.constraints,而不是org.hibernate.validator.constraints】,我们可以直接将这些注解加在我们 JavaBean 的属性上面,这样就可以在需要校验的时候进行校验了,非常方便!- 校验的时候我们实际用的是 Hibernate Validator 框架。Hibernate Validator 是 Hibernate 团队最初的数据校验框架,Hibernate Validator 4.x 是 Bean Validation 1.0(JSR 303)的参考实现,Hibernate Validator 5.x 是 Bean Validation 1.1(JSR 349)的参考实现,目前最新版的 Hibernate Validator 6.x 是 Bean Validation 2.0(JSR 380)的参考实现。
- 一些常用的字段验证的注解
- 验证请求体(RequestBody):
我们在需要验证的参数上加上了@Valid注解
,如果验证失败,它将抛出MethodArgumentNotValidException。 - 验证请求参数(Path Variables 和 Request Parameters):
不要忘记在类上加上 @Validated 注解了,这个参数可以告诉 Spring 去校验方法参数。
- 数据的校验的重要性就不用说了,
- Part1-3.Spring Boot 日志配置
- 使用xml配置日志保存(并不需要pom配置slf4j依赖,starter里面已经配置了依赖了)
- 这个默认不用配置pom依赖,最新的spring-boot-starter-web中已经集成了
- SpringBoot日志配置步骤:
- 1、在项目的resources目录下创建一个【logback-spring.xml】日志配置文件
- 日志配置文件的名称只要是一 logback开头就行,测试使用log.xml并不会生成日志。
合法名称:logback.xml 、logback-spring.xml
- 要配置logback-spring.xml,springboot会默认加载此文件,【为什么不配置logback.xml,因为logback.xml会先application.properties加载,这就说明logback.xml不一定会生效,而logback-spring.xml会后于application.properties加载,这样我们在application.properties文中设置日志文件名称和文件路径才能生效
- 日志配置文件的名称只要是一 logback开头就行,测试使用log.xml并不会生成日志。
- 2、编写xml文件内容:【在当前文件夹下会创建一个【poslog/2022-10/17】的文件夹,里面会按天生成日志:【2022-10-17.log】】
- 咱SpringBoot的.yml以及.properties都没出现,这哪行。
- 日志配置在d盘
在application.yml中配置
- 日志配置在d盘
- 咱SpringBoot的.yml以及.properties都没出现,这哪行。
- 3、在项目中咋用呢,其实就是:【启动一个项目,直接将logback-spring.xml文件复制到resources目录下就可以实现日志文件记录。非常方便。】
//... private Logger logger = LoggerFactory.getLogger(TestController.class); ... logger,info(....);
- 1、在项目的resources目录下创建一个【logback-spring.xml】日志配置文件
- 使用xml配置日志保存(并不需要pom配置slf4j依赖,starter里面已经配置了依赖了)
- Part1-4.Actuator:
SpringBoot自带监控功能Actuator
,可以帮助实现对程序内部运行情况监控,比如监控状况、Bean加载情况、配置属性日志信息等。【相较传统的 Spring 框架,Spring Boot 的一大亮点是引入了内置的监控机制,这是通过 Actuator 组件(常见的包括内存信息、JVM 信息、垃圾回收信息等)来实现的
。基于 Actuator 组件,一方面我们可以查看包含自动配置在内的应用程序详细信息,另一方面可以实时监控该应用程序的运行时健康状态。】
- 使用步骤:
- 导入依赖坐标
- 访问http://localhost:8080/acruator
可以开启所有的监控endpoint:
- 导入依赖坐标
- SpringBoot监控- Spring Boot Admin
- 特点:
- Spring Boot Admin是一个开源社区项目, 用于管理和监控SpringBoot应用程序
- Spring Boot Admin有两个角色,客户端(Client)和服务端(Server)。
- 应用程序作为Spring Boot Admin Client向为Spring Boot Admin Server注册
- Spring Boot Admin Server的UI界面将Spring Boot Admin Client的Actuator Endpoint上的一些监控信息。
- Spring Boot Admin使用步骤:
- 特点:
- 使用步骤:
- SpringBoot监听机制:SpringBoot在项目启动时,会对几个监听器进行回调,我们可以实现这些监听器接口并重写里面的方法,在项目启动时完成一些操作。【SpringBoot的run()方法启动源码解析](链接:https://pan.baidu.com/s/1qGjL_APK1yap4SrhQudA-Q 提取码:1234 】
- Springboot的监听器有两类:
- ApplicationContextInitializer.
- SpringApplicationRunListener、
- CommandLineRunner.
SpringBoot提供了两个接口来实现Spring容器启动完成后执行的功能,两个接口分别为CommandLineRunner和ApplicationRunner【Spring应用启动过程中,肯定是要自动扫描有@Component那四个兄弟注解的类,加载类并初始化对象进行自动注入。加载类时首先要执行static静态代码块中的代码,之后再初始化对象时会执行构造方法。在对象注入完成后,调用带有@PostConstruct注解的方法。当容器启动成功后,再根据@Order注解的顺序调用CommandLineRunner和ApplicationRunner接口类中的run方法。】
- Spring Boot 实现启动过程中执行代码,或启动成功后执行,是有很多种方式可以选择,我们可以在static代码块中实现,也可以在构造方法里实现,也可以使用@PostConstruct注解实现。也
可以去实现Spring的ApplicationRunner与CommandLineRunner接口去实现启动后运行的功能
。- java自身的启动时加载方式
- static静态代码块,在类加载的时候即自动执行。
- 构造方法:在对象初始化时执行。执行顺序在static静态代码块之后。
- Spring启动时加载方式:
- @PostConstruct注解:PostConstruct注解使用在方法上,
这个被PostConstruct注解的方法在对象依赖注入初始化之后执行
。 SpringBoot提供了两个接口来实现Spring容器启动完成后执行的功能,两个接口分别为CommandLineRunner和ApplicationRunner【这两个接口需要实现一个run方法,将代码在run中实现即可。这两个接口功能基本一致,其区别在于run方法的入参。ApplicationRunner的run方法入参为ApplicationArguments,而CommandLineRunner的run方法入参为String数组。】
- ApplicationArguments:在Spring应用运行时使用的访问应用参数。即我们可以获取到SpringApplication.run(…)的应用参数。
当有多个类实现了CommandLineRunner和ApplicationRunner接口时,可以通过在类上添加@Order注解来设定运行顺序
。
- @PostConstruct注解:PostConstruct注解使用在方法上,
- java自身的启动时加载方式
- Spring Boot 实现启动过程中执行代码,或启动成功后执行,是有很多种方式可以选择,我们可以在static代码块中实现,也可以在构造方法里实现,也可以使用@PostConstruct注解实现。也
- ApplicationRunner
- Springboot的监听器有两类:
PART2:SpringBoot实战
- Part2-1:SpringBoot实战步骤:
- 创建Maven项目
- 导入SpringBoot起步依赖
- 定义Controller
- 使用SpringBoot和Spring构建的项目,业务代码编写方式完全一样。
- 进行项目开发时需要考虑的问题:
- 比如:怎样导入静态资源、导入哪些静态资源
- 静态资源的配置【Springboot中文文档关于静态内容:http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/spring-boot-features.html#boot-features-spring-mvc-static-content】:默认情况下,Spring Boot 将在 classpath 或者 ServletContext 根目录下从名为 /static (/public、/resources 或 /META-INF/resources)目录中服务静态内容。它使用了 Spring MVC 的 ResourceHttpRequestHandler,因此你可以通过添加自己的 WebMvcConfigurerAdapter 并重写 addResourceHandlers 方法来修改此行为。
- 静态文件或者叫静态资源的加载顺序跟咱们下面的CLASSPATH_RESOURCE_LOCATIONS这个String数组中定义的优先级顺序一样:resource>static>public
- 静态文件或者叫静态资源的加载顺序跟咱们下面的CLASSPATH_RESOURCE_LOCATIONS这个String数组中定义的优先级顺序一样:resource>static>public
- WebMvcAutoConfiguration.java配置类中的这个方法:private void addResourceHandler(…)//这个方法不就是关于添加静态资源的
@Override public void addResourcesHandlers(ResourceHandlerRegistry registry){ //如果静态资源已经被自定义(自定义就是指咱们在yml重新配置了spring.factories中的写的xxxAutoConfiguration配置类中的利用注解@EnableConfigurationProperties加载进来的xxxProperties配置文件中的属性们),那么在日志中打印这样一句话,然后直接return,如果你重新在yml说明默认值失效,这整个过程在日志中记录下来 if(!this.resourceProperties.isAddMappings()){ logger.debug("Default resource handling disabled"); return; } //导入静态资源的方式1 addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");//只要是/webjars/***这种形状的信息,都去classpath/......下面去找;这是啥意思呢,就是原来咱们是导jar的方式(导maven坐标)的方式,现在springboot帮咱们通过webjars的方式帮咱们导入 //导入静态资源的方式2 addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> { registration.addResourceLocations(this.resourceProperties.getStaticLocation());//添加注册 if(this.servletContext != null){ ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION); registration.addResourceLocations(resource); } }); }
this.resourceProperties.getStaticLocation()//静态资源的目录
- 或者说,
Web相关的静态资源的加载过程等配置的源码,都在WebMvcAutoConfiguration.java的WebMvcConfigurerAdapter 的 addResourceHandlers 等方法中
- 或者说,
- 先全局搜索到WebMvcAutoConfiguration.java,再找到里面的WebMvcAutoConfigurationAdapter,WebMvcAutoConfigurationAdapter里面有个方法叫addResourceHandlers,在这个addResourceHandlers方法里面就是三个if去判断
- 静态资源的配置【Springboot中文文档关于静态内容:http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/spring-boot-features.html#boot-features-spring-mvc-static-content】:默认情况下,Spring Boot 将在 classpath 或者 ServletContext 根目录下从名为 /static (/public、/resources 或 /META-INF/resources)目录中服务静态内容。它使用了 Spring MVC 的 ResourceHttpRequestHandler,因此你可以通过添加自己的 WebMvcConfigurerAdapter 并重写 addResourceHandlers 方法来修改此行为。
- 比如:视图解析器
- springboot是在容器中去找视图解析器的,所以咱们可以给容器自定义添加视图解析器,然后这个类会帮我们将他组合起来。
- 虽然一般不需要自己写,人家springmvc给咱提供的很齐全了,但是如果要自己写或者添加一个视图解析器,就像下面一样
- 比如:模板引擎【Thymeleaf中文文档:https://www.docs4dev.com/docs/zh/thymeleaf/3.0/reference/】【SpringBoot中文文档:http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/spring-boot-features.html#boot-features-webflux-template-engines】
- 咱们写好一个页面模板,模板引擎帮咱们把对应的数据填充到页面中相应位置,常用的比如JSP、FreeMarker、Thymeleaf等,SpringBoot中常用的就是Thymeleaf
- Thymeleaf中的国际化:
- Web相关的国际化等配置的源码,都在WebMvcAutoConfiguration.java的WebMvcConfigurerAdapter 的localeResolver方法中
- 咱们写好一个页面模板,模板引擎帮咱们把对应的数据填充到页面中相应位置,常用的比如JSP、FreeMarker、Thymeleaf等,SpringBoot中常用的就是Thymeleaf
- 比如:怎样导入静态资源、导入哪些静态资源
- 编写引导类
- 启动测试
- SpringBoot在创建项目时,使用jar的打包方式。
- SpringBoot的引导类,是项目入口,运行main方法就可以启动项目。
- 创建Maven项目
- Part2-2:SpringBoot各种整合其他组件步骤:不管整合的是啥,第一步都是在pom.xml中引入依赖坐标,然后开始编写各种含大篇幅注解的类而不用像SSM中那样各种繁琐的xml配置了(之前SSM你要在配置文件中配置,然后IOC,spring帮咱们管理,你要啥你到spring容器中拿(get)就行)
- 装配扩展springMVC
- 整合Junit:
- 搭建SpringBoot工程,这一步只是例程,咱们有项目就直接往咱们已有的项目里面整合就行,别学的太死
- 引入starter-test起步依赖
- 编写测试类
- 添加测试相关注解
- @RunWith(SpringRunner.class)
- @SpringBootTest(classes =启动类.class)
- 编写测试方法
- 整合Redis:
在之前SSM中我们整合Redis,要先导入对应Redis对应的依赖坐标,然后要写一大堆配置,比如Redis的连接信息参数,还得需要在配置里面提供一个RedisTemplate模板对象。【我感觉和之前咱们写的工具类差不多】我们需要操作Redis时就先注入RedisTemplate模板对象,然后调用里面封装好的方法直接进行操作就行
。- 用SpringBoot整合Redis:【没有 Spring Boot 的情况下,如果我们需要引入第三方依赖,需要手动配置,非常麻烦。
但是,Spring Boot 中,我们直接引入一个 starter 即可。比如你想要在项目中使用 redis 的话,直接在项目中引入对应的 starter 即可。引入 starter 之后,我们通过少量注解和一些简单的配置就能使用第三方组件提供的功能了
。】- 搭建SpringBoot工程,这一步只是例程,咱们有项目就直接往咱们已有的项目里面整合就行,别学的太死
- 引入redis起步依赖
- 配置redis相关属性
- 注入RedisTemplate模板
- 编写测试方法,测试,以redis的set、get方法为例
- springboot的redis自动配置原理
- 整合数据库
- 配置数据源:Springboot中文文档:http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/spring-boot-features.html#boot-features-sql
- 具体的java增删改查代码用的是jdbcTemplate:http://felord.cn/_doc/_springboot/2.1.5.RELEASE/_book/pages/spring-boot-features.html#boot-features-using-jdbc-template
- springboot自定义数据源Druid:https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
- Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。
- 整合Mybatis
- 搭建SpringBoot工程
- 引入mybatis起步依赖,添加mysq|驱动
默认的是编译期间生效,你不写就是默认编译器生效
- 编写DataSource和MyBatis相关配置
- 定义表和实体类
- 编写dao和mapper文件/纯注解开发,两种方式:
- 编写dao和mapper文件
- 纯注解开发
- 编写dao和mapper文件
- 测试
- 整合Web相关技术
- 整合权限
其中涉及到的安全方面的框架:(现在用Spring Security或者Shiro一两行代码或者一两个注解就解决了)- Spring Security
- Shiro(另外就是有时候maven的scope写test或者不同生命周期会输出不同信息,或者报错,可以在这里排查一下)
- 源码结构解析(springboot默认(当你啥日志依赖都不在pom.xml中写的时候)用的是commons-logging
- 源码结构解析(springboot默认(当你啥日志依赖都不在pom.xml中写的时候)用的是commons-logging
- Spring Security
- 整合Swagger:Swagger(可以通过swagger给一些比较难理解的属性或者接口增加注释信息显示在swagger页面上,同时实时更新接口文档,并可以在线测试请求,然后看到请求的响应结果包括请求响应对应的头信息,响应体等),在正式发布时必须必须关闭swagger,安全(别人有接口不就可以进行改动了吗)节省内存
Spring或者SpringBoot配置Swagger(集成完下来就到了配置)
- 装配扩展springMVC
- SpringBoot项目开发完毕后,
支持两种方式部署到服务器
:- ①jar包(官方推荐):到服务器的目录下执行这个jar包
- ②war包
- ①jar包(官方推荐):到服务器的目录下执行这个jar包
- 保护 Spring Boot 应用有哪些方法?
- 在生产中使用HTTPS
- 使用Snyk检查你的依赖关系
- 升级到最新版本
- 启用CSRF保护
- 使用内容安全策略防止XSS攻击
- Spring 、Spring Boot 和 Spring Cloud 的关系?
- Spring 最初最核心的两大核心功能 Spring Ioc 和 Spring Aop 成就了 Spring,Spring 在这两大核心的功能上不断的发展,才有了 Spring 事务、Spring Mvc 等一系列伟大的产品,最终成就了 Spring 帝国,到了后期 Spring 几乎可以解决企业开发中的所有问题。
- Spring Boot 是在强大的 Spring 帝国生态基础上面发展而来,发明 Spring Boot 不是为了取代 Spring ,是为了让人们更容易的使用 Spring 。SpringBoot专注于快速方便的开发单个个体微服务(也就是一个有一个jar包)
- Spring Cloud 是一系列框架的有序集合。
是基于SpringBoot的一套微服务解决方案(包含很多东西服务注册与发现、配置中心、服务网关等)(用于将springboot开发的一个又一个单体(也就是jar包)微服务整合并管理起来,为各个微服务直接提供解决那四个问题的集成服务)
。它利用 Spring Boot 的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用 Spring Boot 的开发风格做到一键启动和部署。Spring Cloud 是为了解决微服务架构中服务治理而提供的一系列功能的开发框架,并且 Spring Cloud 是完全基于 Spring Boot 而开发,Spring Cloud 利用 Spring Boot 特性整合了开源行业中优秀的组件,整体对外提供了一套在微服务架构中服务治理的解决方案。
- Part2-3.Java基基老师关于Spring Boot 内置工具类
巨人的肩膀:
https://www.bilibili.com/video/BV1PE411i7CV?p=60
https://www.javalearn.cn/
moon聊技术
苏三说技术(有一个很好的自定义starter的例子,可以关注,然后搜搜看)
Java基基老师的关于Jenkins+docker+springboot 一键自动化部署 SpringBoot 项目,步骤很齐全