Springboot 第一篇
工作闲暇之余,已经看完前两章,在此做一个总结回顾,知识点暂列如下, Spring 的知识点也需要恶补一下
1、 注解组合(注解继承)
2、 Mock 测试 , 前后端分离时测试方法结果
3、 SpringBoot 初始化流程, 自定义初始化事件
4、 配置文件,自定义加载顺序, 多个配置文件; 相互读取属性; 读取pom 文件属性; 随机属性; 多属性;profile 优先级、组合、片段、平台条件
5、 日志 logback slf4j; 日志组;
6、 条件注解 , 自定义条件注解
1、注解组合
注解组合,字面意思理解就是把多个按需要进行拼装组合成一个整体, 方便代码编写和调用。
@SpringBootApplication 此注解多注解在启动类上,见过很多次,但是从未深究此注解的作用,此次学习以它作为代表, 具体代码如下:
6 package org.springframework.boot.autoconfigure; 7 8 import java.lang.annotation.Documented; 9 import java.lang.annotation.ElementType; 10 import java.lang.annotation.Inherited; 11 import java.lang.annotation.Retention; 12 import java.lang.annotation.RetentionPolicy; 13 import java.lang.annotation.Target; 14 import org.springframework.boot.SpringBootConfiguration; 15 import org.springframework.boot.context.TypeExcludeFilter; 16 import org.springframework.context.annotation.ComponentScan; 17 import org.springframework.context.annotation.FilterType; 18 import org.springframework.context.annotation.ComponentScan.Filter; 19 import org.springframework.core.annotation.AliasFor; 20 21 @Target({ElementType.TYPE}) 22 @Retention(RetentionPolicy.RUNTIME) 23 @Documented 24 @Inherited 25 @SpringBootConfiguration 26 @EnableAutoConfiguration 27 @ComponentScan( 28 excludeFilters = {@Filter( 29 type = FilterType.CUSTOM, 30 classes = {TypeExcludeFilter.class} 31 ), @Filter( 32 type = FilterType.CUSTOM, 33 classes = {AutoConfigurationExcludeFilter.class} 34 )} 35 ) 36 public @interface SpringBootApplication { 37 @AliasFor( 38 annotation = EnableAutoConfiguration.class 39 ) 40 Class<?>[] exclude() default {}; 41 42 @AliasFor( 43 annotation = EnableAutoConfiguration.class 44 ) 45 String[] excludeName() default {}; 46 47 @AliasFor( 48 annotation = ComponentScan.class, 49 attribute = "basePackages" 50 ) 51 String[] scanBasePackages() default {}; 52 53 @AliasFor( 54 annotation = ComponentScan.class, 55 attribute = "basePackageClasses" 56 ) 57 Class<?>[] scanBasePackageClasses() default {}; 58 }
关于自定义注解的方法和参数说明见此: https://www.cnblogs.com/cgsdg/articles/15259286.html
@SpringBootApplication 是 @SpringBootConfiguration / @EnableAutoConfiguration / @ComponentScan 三个注解组合而成,自然也拥有这三个注解所代表的功能。
其中 @SpringBootConfiguration 相当于 @Configuration, 使用组合注解的方式为 @Configuration 起了一个别名,含义: 表明该类是一个配置类,且声明该类是一个Bean
@EnableAutoConfiguration 相当于 @AutoConfigurationPackage ,方式同上, 含义:根据jar包依赖,进行自动配置,例如starter包 中的依赖配置
@ComponentScan 注解含义: 会扫描当前类所在的同级包及其子包内的Bean (所以开始做Springboot项目的时候,遇到过目录建立的位置不在此范围,扫描不到Bean,导致的报错)
@AliasFor 为理解为定义别名,也可指定下变量是由哪个注解继承过来的
2、 Mock测试
刚入职开始使用SpringBoot 的时候,被公司大佬要求一直要写Mock 测试,当时并不理解,感觉意义不大,而且由于知识匮乏,没有很好的理解,写起来比较乱,所以后来有机会偷懒就一直都没有写过,此次在书里又发现了Mock 测试,细细看了,才理解了当时大佬的良苦用心😅 需要好好梳理一下,并且开始要熟悉写测试类,标准化把自己的能力补上来, 虽然可以自己通过写模拟接口来做测试, 但是对于调整后的代码,尤其是代码重构,没办法做自动回归测试,而Test 单元测试会在每次运行打包之前自动跑一遍,很有效的预防了一些修改功能后引发的BUG, 但Mock也不是万能的,需要看情况来使用。
首先呢, 还是要先能够熟练的编写Mock测试,技多不压身,别书到用时方恨少了。
Mock使用详情见此:
3、SpringBoot 初始化流程
了解熟悉SpringBoot 初始化流程后,可对项目特殊的情况下加入自己的处理,了解各个对象初始化的顺序,在何时可以加入自己想要添加的自定义情况
4、SpringBoot 的配置文件
一类是@Configuration 注解标记的配置类,本身有一套配置优先级顺序,自己写的配置文件可指定优先级顺序
一类是基础的配置文件: application.properties / application-{profiles}.properties 工程内部的配置文件、同级目录的配置文件、启动命令的指定配置参数 优先级依次增高
除此之外,还可自定义配置文件,并且对齐进行引用, 文件之间属性的相互引用,读取POM 文件的属性, 随机属性,单/多属性的注入, 文件之间的组合、片段、平台条件等灵活配置
5、SpringBoot 的日志
SpringBoot 的日志依赖是 spring-boot-starter-logging.jar ,在spring-boot-starter.jar中依赖;
logging 依赖于此三个包:
logback-classic.jar
log4j-to-slf4j.jar 负责将log4j 日志路由到slf4j
jul-to-slf4j.jar(Java Unit Log,一般情况不建议使用) 负责将jul 日志路由到slf4j,springboot部署到 web应用服务器上是,不会把jul路由到slf4j,是为了避免把其他应用的日志也路由到springboot 应用中
日志框架可分为:
门面类(抽象层/应用程序输出):SLF4J、JCL、JBoss Logging
日志实现:Log4j、Log4j2、LogBack、JUL
默认推荐的是 LogBack + Slf4j , Slf4j作为日志输出门面, LogBack作为日志实现
底层实现会默认把 Log4j \ Log4j2 等日志转到 Slf4j 进行输出, 可进行调整,对starter 依赖进行排除后,引入新的依赖,即可实现
日志的等级: All / DEBUG / INFO / WARN / ERROR / FATAL / NONE
日志组:把多个包设定为一个组,批量配置日志
日志属性示例:
#日志组示例
#把两个包定义为logapp组
logging.group.logapp:com.testlog.app,com.prodlog.app
#为logapp组设定日志级别为TRACE
logging.level.logapp:trace
#将根日志级别设置为WARN logging.level.root=WARN #将org.springframework.web 包及其子包下的所有日志级别设置为DEBUG logging.level.org.springframework.web=DEBUG #设置日志文件 logging.file=app.log logging.path= ./log #用于记录异常的转换字 logging.exception-conversion-word= #指定日志中的日期格式模版 logging.pattern.dateformat= #指定控制台日志的格式模版 logging.pattern.console= #指定输出控制台日志事所用的字符集 logging.charset.console= #指定文件日志的格式模版(只有日志输出到文件时有效) logging.pattern.file= #指定文件日志的字符集(只有日志输出到文件时有效) logging.charset.file= #LogBack 日志设置 #设置将对日志归档的文件名模版 logging.logback.rollingpolicy.file-name-pattern= #设置应用启动时是否清楚日志归档 logging.logback.rollingpolicy.clean-history-on-start= #设置日志文件归档之前的最大大小 logging.logback.rollingpolicy.max-file-size= #设置日志归档在被删除之前所能容纳的最大的大小 logging.logback.rollingpolicy.total-size-cap= #设置保留多少天的日志归档(默认7天) logging.logback.rollingpolicy.max-history=
Logback-spring.xml 的配置, 默认的命令行配置、文件配置; 可指定不同的格式,根据不同的环境进行区别配置
springboot 中在org/springframework/boot/logging/lobback/ 路径下常用的文件如下:
defaults.xml: 提供了转换规则及各种通用配置
console-appender.xml: 定义了一个ConsoleAppender, 用于将日志输出到控制台
file-appender.xml: 定义了一个RollingFileAppender, 用于将日志输出到文件
defaults.xml 文件如下
<?xml version="1.0" encoding="UTF-8"?> <!-- Default logback configuration provided for import --> <included> <conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" /> <conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" /> <conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" /> <property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/> <logger name="org.apache.catalina.startup.DigesterFactory" level="ERROR"/> <logger name="org.apache.catalina.util.LifecycleBase" level="ERROR"/> <logger name="org.apache.coyote.http11.Http11NioProtocol" level="WARN"/> <logger name="org.apache.sshd.common.util.SecurityUtils" level="WARN"/> <logger name="org.apache.tomcat.util.net.NioSelectorPool" level="WARN"/> <logger name="org.eclipse.jetty.util.component.AbstractLifeCycle" level="ERROR"/> <logger name="org.hibernate.validator.internal.util.Version" level="WARN"/> </included>
console-appender.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- Console appender logback configuration provided for import, equivalent to the programmatic initialization performed by Boot --> <included> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>${CONSOLE_LOG_PATTERN}</pattern> </encoder> </appender> </included>
file-appender.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- File appender logback configuration provided for import, equivalent to the programmatic initialization performed by Boot --> <included> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> <file>${LOG_FILE}</file> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern> <maxFileSize>${LOG_FILE_MAX_SIZE:-10MB}</maxFileSize> <maxHistory>${LOG_FILE_MAX_HISTORY:-0}</maxHistory> </rollingPolicy> </appender> </included>
其中 ${FILE_LOG_PATTERN}、${LOG_FILE}、${LOG_PATH} 、${LOG_FILE_MAX_SIZE} 等为占位符,冒号后面为默认值,如果在配置文件中配置了对应的值,将会进行替换
通过上面的代码可以看到,3个xml 文件内都是<included> 标签,定义了对应的<included> 的内容,在自定义logback-spring.xml 的时候可以进行引用,下面是一份典型的 logback.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <!-- 导入logback 通用日志 --> <include resource="org/springframework/boot/logging/logback/default.xml></include> <!-- 导入输入到文件的日志配置 --> <include resource="org/springframework/boot/logging/logback/RollingFileAppender.xml></include> <!-- 指定 root 日志的级别是 Info, 默认输出到控制台 --> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> <!-- 指定 com.testlog.app 日志级别是DEBUG --> <logger name="com.testlog.app" level="DEBUG" /> </configuration>
LogBack扩展, 根据不同的Profile设定不同的配置;
通过标签 <springProfile> 来进行条件配置,例子如下
<?xml version="1.0" encoding="UTF-8" ?> <configuration> <springProfile name="dev | test"> <include resource="org/springframework/boot/logging/logback/defaults.xml /> <property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}" /> <include resource="org/springframework/boot/logging/logback/concole-appender.xml" /> <include resource="org/springframework/boot/logging/lobback/file-appender.xml" /> <root level="DEBUG"> <appender-ref ref="CONSOLE" /> <appender-ref ref="FILE" /> </root> <logger name="com.testlog.app" level="DEBUG" /> </springProfile> <springProfile name="prod"> <include resource="..." /> <root level="INFO"> <appender-ref ref="FILE" </root> </springProfile> </configuration>
logback 使用环境属性, <springProperty> 标签来指定,该标签支持以下几个属性:
name: 为读取到的属性指定名字
source: 指定读取 SpringBoot 的哪个配置属性,此处推荐“烤串” 写法
scope: 指定存储该配置属性的作用域
defaultValue:默认值
示例如下
<!-- 定义 fluentHost 变量保存 myapp.fluentd.host 配置的值 --> <springProperty scope="context" name="fluentHost" source="myapp.fluentd.host" defaultValue="localhost" /> <appender name="FLUENT" class="ch.qos.logback.more.appenders.DataFluentAppender"> <!-- 使用前面定义的 fluentHost 属性 --> <remoteHost>${fluentHost}</remoteHost>
6、条件注解 、 自定义自动配置注解
@Conditional 条件注解, 根据类、Bean、变量是否存在来判定是否需要生成Bean, 可支持如下几类条件
类条件注解:@ConditionalOnClass 、 @ConditionalOnMissingClass
Bean条件注解: @ConditionalOnMissingBean、 @ConditionalOnSingleCandidate 、 @ConditionalOnBean、 @ConditionalonMissingFilterBean
属性条件注解: @ConditionalOnProperty
资源条件注解: @ConditionalOnResource
Web 应用条件注解: @ConditionalOnWebApplication、@ConditionalOnNotWebApplication、 @ConditionalOnWarDeployment
SpEL 表达式条件注解: @ConditionalOnExpression
特殊条件注解: @ConditionalOnCloudPlatform、 @ConditionalOnJava 、 @ConditionalOnJndi 、 @ConditionalOnRepositoryType
自定义自动配置, 写一个 stater 配置
浙公网安备 33010602011771号