SpringBoot 特性
SpringApplication:
SpringApplication类提供了快捷启动Spring应用的.run静态方法,默认启动项目打印日志级别为INFO
启动失败,注册的失败分析器(FailureAnalyzers)会提供错误信息
Banner:
启动Spring应用时输出的字符画称为Banner,设置Banner方法有三个
在classpath中添加banner.txt改变Banner样式
在application.properties设置Banner参数
在入口方法main函数中使用 setBannerMode或者setBanner方法设置Banner
1
2
3SpringApplication app=new SpringApplication(App.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
Logging:
日志格式解析:日期时间-日志级别-进程ID-[线程名]-日志名(源class类名)-日志信息
日志系统配置:可在application.properties中配置日志相关参数
日志级别:通过设置logging.level.*=“LEVEL”来配置不同模块的日志以不同的日志级别输出,一般日志级别从低到高有ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
1
2
3
4
5
6#root日志以WARN级别输出
logging.level.root=WARN
#springframework.web日志以DEBUG级别输出
logging.level.org.springframework.web=DEBUG
#hibernate日志以ERROR级别输出
logging.level.org.hibernate=ERROR日志输出文件:可以通过设置logging.file或者logging.path属性默认记录ERROR+WARN+INFO级别的日志记录写入文件中
| logging.file | logging.path | value | 描述 |
| ———— | ———— | ———- | —————————— |
| 无设置 | 无设置 | | 记录到控制台 |
| 设置 | 无设置 | log/my.log | 写到特定目录的特定文件名中 |
| 无设置 | 设置 | var/log | 写到特定目录的spring.log文件中 |日志高级配置:若要设定更高级的日志配置需要使用logging.config指定相应的日志配置文件或者使用相应的*-spring.xml配置文件让SpringBoot帮我们自动配置,这里我们采用log4j2日志系统来进行系统日志配置
加载log4j2依赖:由于在spring-boot-starter中集成了logback日志系统依赖,我们需要先去除logback依赖再加载log4j2依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<!--去除logback依赖-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--加载log4j2依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>配置log4j2配置文件:命名配置文件为log4j2-spring.xml(SpringBoot自动加载)或者自定义配置文件名称但是需要在application.properties里配置logging.config选项
1
logging.config=classpath:log4j2.xml
编写log4j2配置文件:
简单的log4j2配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<?xml version="1.0" encoding="UTF-8"?>
<!--配置根节点 属性:status-打印日志级别 monitorinterval-监测自动重新配置时间 单位秒-->
<Configuration>
<!--日志输出方式组件-->
<!--通常有Console File RollingFile节点-->
<!--还有Socket远程服务器输出 Async中转输出至别的Appender-->
<Appenders>
<!--Console控制台输出节点-->
<Console name="Console" target="SYSTEM_OUT">
<!--输出消息规则-->
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<!--指定日志输出级别和输出方式的组件 通常有Root Logger节点-->
<Loggers>
<!--指定特定的包/类使用的日志级别-->
<Logger name="com.example" level="INFO"/>
<!--指定所有包/类默认使用的日志级别-->
<Root level="WARN">
<!--指定日志输出到哪个Appender-->
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>较完整的log4j2配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67<?xml version="1.0" encoding="UTF-8"?>
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="WARN" monitorInterval="30">
<!--先定义所有的appender-->
<appenders>
<!--控制台输出配置-->
<console name="Console" target="SYSTEM_OUT">
<!--输出日志的格式-->
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
</console>
<!--文件输出,这个log每次运行程序会自动清空,由append属性决定,适合临时测试使用-->
<File name="log" fileName="testLog/test.log" append="false">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/>
</File>
<!-- 这个会打印出所有的info及以下级别的信息,每次大小超过size,则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档-->
<RollingFile name="RollingFileInfo" fileName="infoLogs/info.log"
filePattern="infoLogs/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
<RollingFile name="RollingFileWarn" fileName="warnLogs/warn.log"
filePattern="warnLogs/logs/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="warn" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
<!-- DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了20 -->
<DefaultRolloverStrategy max="20"/>
</RollingFile>
<RollingFile name="RollingFileError" fileName="errorLogs/error.log"
filePattern="errorLogs/$${date:yyyy-MM}/error-%d{yyyy-MM-dd}-%i.log">
<ThresholdFilter level="error" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="[%d{HH:mm:ss:SSS}] [%p] - %l - %m%n"/>
<Policies>
<TimeBasedTriggeringPolicy/>
<SizeBasedTriggeringPolicy size="100 MB"/>
</Policies>
</RollingFile>
</appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
<logger name="org.springframework" level="INFO"></logger>
<!--<logger name="org.mybatis" level="INFO"></logger>-->
<root level="all">
<appender-ref ref="Console"/>
<appender-ref ref="log"/>
<appender-ref ref="RollingFileInfo"/>
<appender-ref ref="RollingFileWarn"/>
<appender-ref ref="RollingFileError"/>
</root>
</loggers>
</configuration>使用log自定义输出日志:
1
2
3
4
5
6
7
8//在类中定义log工具变量
private static Logger log = LogManager.getLogger(DemoController.class);
//在方法中可以使用log.日志level(String)输出对应级别的日志
log.trace("trace");
log.debug("debug");
log.info("info");
log.warn("warn");
log.error("error");
Lombok:
Lombok是一种微型框架工具,有助于帮助减少模板代码使得开发更加快速,具体表现为可以使用注解生成Getter、Setter、toString、hashCode、constructor方法等,下面介绍在Spring Boot中使用Lombok
添加Lombok依赖:由于spring-boot-dependencies中已经配置了lombok依赖的参数,如version和scope,我们可以直接添加依赖
1
2
3
4
5<!--lombok生成代码工具-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
在代码中使用Lombok:我们可以在需要使用生成Getter、Setter、Constructor的类中使用注解的方式而不是IDEA生成的方式生成相应的方法代码,常用的注解加粗,详细解释可查看Lombok官方文档
| 注解 | 作用 |
| ———————– | ————————————————– |
| @Getter | 生成类属性的getter方法 |
| @Setter | 生成类属性的setter方法 |
| @ToString | 生成类所有属性的toString方法 |
| @EqualsAndHashCode | 生成类的equal和hashCode方法 |
| @NoArgsConstructor | 生成类的无参构造方法 |
| @AllArgsConstructor | 生成类的全参数的构造方法 |
| @Data | 相当于@Getter+@Setter+@ToString+@EqualsAndHashCode |
| @Log4j | 为类生成一个名为log的log4j日志对象 |
| @NonNull | 标识在实体对象上自动进行非空校验 |
Hibernate Validator:
后台经常需要校验所接收的参数,如是否为空、长度规定、正则判定等,spring-boot-starter-web 依赖中集成了hibernate validator 提供了一套较为完善、便捷的验证实现方式
简单参数的验证:在所需验证的参数的类(如controller)上添加@Validated注解,在需要验证传入参数的方法的参数列表中添加验证注解
1
2
3
4
5
6
7
8
9
10
11
public class DemoController{
"/") (
public void simpleParamsValidate(
@Size(min=3,max=10,message="名字长度为3-10") @RequestParam("name") String name,
@Range(min=1,max=99,message="年龄只能从1-99") @RequestParam("age") String age
){
//toDo...
}
}复杂的对象参数的验证:对于复杂的参数我们可以编写一个Model对象进行接收,这样直接在Model对象内部编写注解进行属性的验证,对于在Web开发中的POST请求我们可以直接使用@RequestBody注解将接收的json字符串注入到Model对象中进行验证,并利用BindingResult处理验证结果
Person.java(Model对象)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Person {
"姓名不能为空") (message =
3,max=10,message = "名字长度为3-10") (min=
private String name;
"年龄不能为空") (message =
1, max = 99, message = "年龄只能从1-99") (min =
private String age;
private String email;
"密码不能为空") (message =
3,max=10,message = "密码长度为3-10") (min=
private String password;
}DemoController中的validateModel方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25//用@RequestBody将JSON字符串直接注入至JAVA对象中需要HTTP方法使用POST
//@Valid注解验证注入对象的数据是否符合注解规定
//BindingResult存储错误消息
"/validateModel",method = RequestMethod.POST) (value =
public Map validateModel(
@RequestBody @Valid Person person,BindingResult result
){
//BindingResult.hasErrors存储是否存在验证问题
if(result.hasErrors()){
ArrayList errorArray=new ArrayList();
//BindingResult.getAllErrors()得到一个ObjectError对象的数组
for (ObjectError error : result.getAllErrors()) {
//ObjectError对象.getDefaultMessage()可得到错误消息
errorArray.add(error.getDefaultMessage());
}
Map<String,Object> map=new HashMap<>();
map.put("Error",errorArray);
return map;
}else{
Map<String,Object> map=new HashMap<>();
map.put("GetParams",person);
return map;
}
}设置失败快速返回:Hibernate Validator 有两种验证模式:
- 普通模式(默认):校验完所有属性,返回所有验证失败信息
- 快速失败返回模式:只要校验到一个失败,直接返回
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class ValidatorConfig {
"unchecked") (
public Validator validator(){
ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
.configure()
.failFast(true) //配置失败快速返回模式
.buildValidatorFactory();
Validator validator = validatorFactory.getValidator();
return validator;
}
}常见的验证注解:
其余校验技巧:详解可参考Mr.yang.localhost的博客文章
- 级联校验:验证的对象A中有其他需要验证的对象B,需要在对象A中使用注解@Valid 标记对象B
- 分组校验:在不同场景需要校验对象的不同属性,如注册中校验name、age等,但是用户操作要校验id等
- 自定义验证器