SpringBoot
# 简介
SpringBoot是由Pivotal团队在2013年开始研发、2014年4月发布第一个版本的全新开源的轻量级框架。它基于Spring4.0设计,不仅继承了Spring框架原有的优秀特性,而且还通过简化配置来进一步简化了Spring应用的整个搭建和开发过程。另外SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性等问题得到了很好的解决。
IDE:Intellij IDEA
# hello world
直接使用IDEA新建Spring Initializr,然后和创建maven项目一样修改group和artifact,type为maven project(默认就是),值得一提的是可以直接使用jar方式发布到生产环境,所以packaging可以选择jar,然后next,会要求选择依赖,这里先勾选个web->spring web,以后需要可以追加,之后next-finish。
然后找到src/main/java/包名/里面应该应该会有一个这样的文件
package com.alight.springbootdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringBootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
可以直接在里面写controller 像这样:
package com.alight.springbootdemo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@SpringBootApplication
public class SpringBootDemoApplication {
@RequestMapping("/")
String home() {
return "Hello World!";
}
public static void main(String[] args) {
SpringApplication.run(SpringBootDemoApplication.class, args);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
然后打开浏览器 访问localhost:8080 (opens new window)
然后它就输出了hello world,so cool。
# 创建可执行Jar
通过创建可以在生产环境中运行的完全独立的可执行jar文件来结束示例。可执行jar(有时称为“fat jars”)是包含您的已编译类以及代码需要运行的所有jar依赖项的归档文件。
可执行Jar和Java
Java没有提供加载嵌套jar文件(jar中本身包含的jar文件)的标准方法。如果您要分发独立的应用程序,则可能会出现问题。
为了解决这个问题,许多开发人员使用uber jars。uber jar将来自应用程序所有依赖项的所有类打包到单个存档中。这种方法的问题在于,很难查看应用程序中包含哪些库。如果在多个jar中使用相同的文件名(但具有不同的内容),也可能会产生问题。
Spring Boot采用了另一种方法,实际上允许您直接嵌套jar。
要创建可执行jar,我们需要将添加spring-boot-maven-plugin
到pom.xml
。为此,请在该dependencies
部分下方插入以下行:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2
3
4
5
6
7
8
如果刚才是使用上述方式创建的项目,则应该会自动添加该插件
在项目根目录输入mvn package
此时,如果查看target目录,则应该看到spring-boot-demo-0.0.1-SNAPSHOT.jar。该文件的大小应为10 MB左右。如果您想窥视内部,可以使用jar tvf``
$ jar tvf target / spring-boot-demo-0.0.1-SNAPSHOT.jar
您还应该在target目录中看到一个更小的文件spring-boot-demo-0.0.1-SNAPSHOT.jar.original。这是Maven在Spring Boot重新打包之前创建的原始jar文件。
要运行该应用程序,请使用以下java -jar命令:
$ java -jar target / spring-boot-demo-0.0.1-SNAPSHOT.jar
和以前一样,要退出该应用程序,请按ctrl-c。
# 格式化JSON时间
在REST API中,返回的时间(json)将会是标准时间,加上时区等一大串字符,可读性会比较差。通常情况下,我们希望返回一个可读性比较强的时间,因此需要一些简单的配置。
spring
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
2
3
4
通过以上配置,返回的时间格式可读性明显提升。
# Hot Swap
弃坑,并不好用,经常出现更新不及时等其他问题。
总结:不如手动重新启动省心 - -
厌倦了在idea每次修改代码后都需要重新启动了?
ok,是时候使用热插拔(有的时候也有人叫热交换,热部署,whatever,总之都差不多)来简化你的开发了。(当你觉得花了太多时间在等待时,你就应该考虑了解新技术来简化这个过程了)
环境依然是springboot+idea
首先你需要导入spring-boot-devtools,没有加上版本是因为通常都配置了spring-boot-starter-parent
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
2
3
4
5
6
同时还需加上插件配置
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--如果要使用构建插件从Maven或Gradle重新启动,则必须将forking设置保留为enabled-->
<fork>true</fork>
</configuration>
</plugin>
2
3
4
5
6
7
8
之后打开IDEA设置,搜索compiler找到Build project automatically
勾选。
再然后在IDEA中使用快捷键 Ctrl+Shift+Alt+/
,点击Registry...
,找到 compiler.automake.allow.when.app.running
,勾选--->close。
重启进行测试,发现功能正常生效,但是每次修改都需等待片刻(目测5s+)才能自动重新部署。
注意,如果修改导致代码出现错误而导致应用自动退出,则仍需要手动重启。
配合浏览器livereload插件食用效果更佳
更多参考
https://www.jetbrains.com/help/idea/spring-boot.html#application-update-policies (opens new window)
# PathVariable
路径参数可以说是十分常见的功能了。
这里简单贴个demo
@GetMapping("products/{id}")
@ApiOperation("通过id获取指定产品信息")
public Product getOne(@PathVariable String id){
return ProductService.getById(id);
}
2
3
4
5
# 全局异常捕获
创建一个如下所示的配置类即可,可自行添加特殊捕获处理的异常
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class) // 可换成更细粒度的异常捕获
public ResponseEntity error(Exception e) {
e.printStackTrace();
return ResponseEntityFactory.build(HttpStatus.BAD_REQUEST, e.getCause().getMessage());
}
}
2
3
4
5
6
7
8
9
10
404异常捕获(未存在的url)需要添加以下配置
application.yml
spring:
mvc:
throw-exception-if-no-handler-found: true # non-existed url will throw exception
2
3
然后自定义error控制器
@RestController
@RequestMapping("/")
public class BaseController implements ErrorController {
@RequestMapping("error")
public ResponseEntity error() {
// return anything you want
return ResponseEntityFactory.build(HttpStatus.NOT_FOUND);
}
@Override
public String getErrorPath() {
return "error";
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 参数校验
在 Spring Boot 2.3 1前,spring-boot-starter-web
自带spring-boot-starter-validation
,如果是没有自带的话,则需要自己添加
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2
3
4
在controler中需要校验的参数前加上 @valid
注解
@PostMapping("products")
public ResponseEntity insert(@Valid Products products) {
...
}
2
3
4
除了实体类,单个参数也可以直接使用该注解并加上想应约束注解即可
然后在相关实体类加上相应的注解进行约束即可
常见的注解
注解 | 描述 |
---|---|
@Null | 必须为Null |
@NotNull | 不能为Null |
@AssertTrue | 必须为True |
@AssertFalse | 必须为false |
@Min(value) | 数字类型的最小值 |
@Max(value) | 数字类型的最大值 |
@DecimalMin(value) | 数字类型的最小值 |
@DecimalMax(value) | 数字类型的最大值 |
@Size(max=, min=) | 字符或者集合的大小区间 |
@Digits (integer, fraction) | 数字取值区间 |
@Past | 必须是过去的时间 |
@Future | 必须是将来的时间 |
@Pattern(regex=,flag=) | 正则匹配 |
@NotBlank(message =) | 字符串非Null,且trim之后大于0 |
邮件地址 | |
@Length(min=,max=) | 字符串长度范围 |
@NotEmpty | 字符串非空 |
@Range(min=,max=,message=) | 元素范围限制 |
# 统一返回结果
Spring自带的ReponseEntity+HttpStatus十分好用。
备份一个RepsoneEntityFactory
public class ResponseEntityFactory {
private ResponseEntityFactory() {
}
public static ResponseEntity build(HttpStatus httpStatus, Object data) {
Map resultMap = null;
if (data instanceof Map) {
resultMap = (Map) data;
} else {
resultMap = new HashMap();
resultMap.put("data", data);
}
resultMap.put("code", httpStatus.value());
resultMap.put("msg", httpStatus.getReasonPhrase());
return new ResponseEntity(resultMap, httpStatus);
}
public static ResponseEntity build(HttpStatus httpStatus, String msg, Object data) {
Map resultMap = null;
if (data instanceof Map) {
resultMap = (Map) data;
} else {
resultMap = new HashMap();
resultMap.put("data", data);
}
resultMap.put("code", httpStatus.value());
resultMap.put("msg", msg);
return new ResponseEntity(resultMap, httpStatus);
}
public static ResponseEntity build(HttpStatus httpStatus) {
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("code", httpStatus.value());
resultMap.put("msg", httpStatus.getReasonPhrase());
return new ResponseEntity(resultMap, httpStatus);
}
public static ResponseEntity build(HttpStatus httpStatus, String msg) {
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("code", httpStatus.value());
resultMap.put("msg", msg);
return new ResponseEntity(resultMap, httpStatus);
}
}
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
# 日志系统
SpringBoot默认采Logback进行日志记录,并且默认输出info级别的日志到控制台。
日志级别分为以下几个,ERROR
,WARN
,INFO
,DEBUG
,FATAL
,OFF
,TRACE
.日志等级越高,输出的日志越多,比如在info级别下,会同时输出info、warn、error三个级别的日志。切换等级只需要在application.xml
配置文件指定logging.level.root = xxx
即可(yaml同理)。
for example:
logging.level.root=warn
logging.level.org.springframework.web=debug
logging.level.org.hibernate=error
2
3
TRACE级别可以追踪到web容器的日志
Logback没有FATAL等级
文件日志默认是没有打开的(默认输出到控制台),需要手动在配置文件指定logging.file.name
,它可以是一个绝对路径,也可以是相对路径。
默认情况下只会保存7天日志,相关的配置为logging.file.max-history
。
默认情况下日志文件的大小限制为10MB,相关的配置为logging.file.max-size
。
logging.file.total-size-cap
:该属性用于限制压缩文件的总大小。(隔天启动发现前一天的日志被放进.gz
压缩包。)
logging.file.clean-history-on-start
:清除历史日志在应用启动时。
日志的配置文件与实际的日志基础结构无关。因此,Spring Boot不会管理特定的配置文件(例如Logback的logback.configurationFile
)。
日志分组
举个例子,将tomcat的日志归到一组,包名需要自己配置,设置日志级别为TRACE.
logging.group.tomcat=org.apache.catalina, org.apache.coyote, org.apache.tomcat
logging.level.tomcat=TRACE
2
SpringBoot默认包含了web和sql组,他们包含的包如下所示:
Name | Loggers |
---|---|
web | org.springframework.core.codec , org.springframework.http , org.springframework.web , org.springframework.boot.actuate.endpoint.web , org.springframework.boot.web.servlet.ServletContextInitializerBeans |
sql | org.springframework.jdbc.core , org.hibernate.SQL , org.jooq.tools.LoggerListener |
日志关闭钩子(Log Shutdown Hook),可以让你在启动程序结束立即关闭日志记录。
logging.register-shutdown-hook=true
自定义日志配置文件,Logback的自定义配置文件名为logback-spring.xml
,更多参考boot-features-custom-log-configuration (opens new window)
仿springboot默认日志格式
- 添加pid转换器
ProcessIdConverter
public class ProcessIdConverter extends ClassicConverter {
@Override
public String convert(ILoggingEvent iLoggingEvent) {
return ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
}
}
2
3
4
5
6
7
8
- 注册pid key
<conversionRule conversionWord="pid"
converterClass="xyz.ayay.servicebase.config.ProcessIdConverter" />
2
- 修改pattern
%yellow(%date{yyyy-MM-dd HH:mm:ss.SSS}) %highlight(%-5level) %magenta(%pid) --- [%15.15thread] %-60.60cyan(%logger{40}) : %m%n
同时Spring默认提供了大量的Logback扩展,详情参考boot-features-logback-extensions (opens new window)
具体在SpringBoot中,只需要在类头使用@Slf4j
注解,就可以在类中使用log.xxx记录日志了