SpringBoot-start

笔记参考于柏码知识库

SpringBoot简化了配置过程,只需导入相应启动器(starter)依赖。

基础

创建项目

在官网少量配置就能快速生成SpringBoot模板:https://start.spring.io/

并且IDEA已经将此工具集成到了内部,创建项目选择Spring Initializr类型,之后选择模块。

常用模块快速整合

导入依赖,无需配置就可以正常使用:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

SpringBoot支持自动包扫描, 不需要配置,在主类所在包内任意路径创建组件都可以生效。

对象也可以直接以JSON形式返回客户端,SpringBoot官方默认使用的是Jackson和Gson的HttpMessageConverter来进行配置:

1
2
3
4
5
6
7
8
9
@ResponseBody
@GetMapping("/")
public Student index(){
Student student = new Student();
student.setName("小明");
student.setSex("男");
student.setSid(10);
return student;
}

添加WebMvc类:

1
2
3
4
5
6
7
8
9
10
11
12
13
//只需要添加Configuration用于注册配置类,不需要其他任何注解,已经自动配置好了
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return HandlerInterceptor.super.preHandle(request, response, handler);
}
});
}
}

导入SpringSecurity框架即可生效,并设置了一个用户,用户名为user,密码为随机密码:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

额外配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//依然只需要Configuration注解即可,不需要其他配置
@Configuration
public class SecurityConfiguration {

//配置方式跟之前SSM阶段是一样的
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> {
auth.anyRequest().authenticated();
})
.formLogin(conf -> {
conf.loginPage("/login");
conf.loginProcessingUrl("/doLogin");
conf.defaultSuccessUrl("/");
conf.permitAll();
})
.build();
}
}

自定义运行器

编写自定义的ApplicationRunner,在项目启动完成时执行:

1
2
3
4
5
6
7
@Component
public class TestRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("我是自定义执行!");
}
}

配置文件

在application.properties中进行配置编写。

可以使用@Value来访问配置文件中的值:

1
test.data=100
1
2
3
4
5
@Controller
public class TestController {
@Value("${test.data}")
int data; //直接从配置中去取
}

可以将配置文件后缀修改为yml或yaml,来使用对应格式编写。如数据源配置:

1
2
3
4
5
6
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver

对于@Mapper文件,只需要在对应接口添加@Mapper注解,或在配置类上添加@MapperScan即可(二选一)。

SpringSecurity与SpringBootMvc配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
spring:  
# Spring Mvc相关配置
mvc:
static-path-pattern: /static/** #静态资源解析地址
# Spring Security 相关配置
security:
filter:
order: -100 #Spring Security 过滤器优先级
user:
name: 'admin' #默认登录用户名
password: '123456' #默认登录密码
roles: #默认用户的角色
- admin
- user

打包

可以一键打包为jar,然后一行命令运行:

1
java -jar demo-0.0.1-SNAPSHOT.jar

还可以直接编译为操作系统原生程序,需要使用GraalVM环境。但Mybatis目前不支持Native-Image。

日志系统

日志门面和日志实现

日志门面(Facade),如SlF4j相当于一种规范,只提供统一的日志使用接口。而起具体实现便是日志实现。

SpringBoot为了统一日志框架的使用,进行了以下处理:

  • 直接将其他依赖以前的日志框架剔除
  • 导入对应日志框架的Slf4j中间包
  • 导入自己官方指定的日志实现,并作为Slf4j的日志实现层

打印项目日志信息

SpringBoot使用的是Slf4j作为日志门面,Logback作为日志实现,对应的依赖为:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>

在使用Lombok后,添加@Slf4j注解即可直接打印信息:

1
2
3
4
5
6
7
8
9
10
11
12
@Slf4j
@Controller
public class MainController {

@ResponseBody
@GetMapping("/test")
public User test(){
log.info("用户访问了一次测试数据");
return mapper.findUserById(1);
}

...

日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,默认只会打印INFO以上级别的信息。

多环境配置

可以通过配置文件指定,并创建类似application-dev.yml和application-prod.yml的配置文件:

1
2
3
spring:
profiles:
active: dev

打包时,可以通过Maven配置多环境:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!--分别设置开发,生产环境-->
<profiles>
<!-- 开发环境 -->
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<environment>dev</environment>
</properties>
</profile>
<!-- 生产环境 -->
<profile>
<id>prod</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<environment>prod</environment>
</properties>
</profile>
</profiles>

排除其他环境的配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<resources>
<!--排除配置文件-->
<resource>
<directory>src/main/resources</directory>
<!--先排除所有的配置文件-->
<excludes>
<!--使用通配符,当然可以定义多个exclude标签进行排除-->
<exclude>application*.yml</exclude>
</excludes>
</resource>

<!--根据激活条件引入打包所需的配置和文件-->
<resource>
<directory>src/main/resources</directory>
<!--引入所需环境的配置文件-->
<filtering>true</filtering>
<includes>
<include>application.yml</include>
<!--根据maven选择环境导入配置文件-->
<include>application-${environment}.yml</include>
</includes>
</resource>
</resources>

之后可以将Maven的environment属性传递给SpringBoot配置文件:

1
2
3
spring:
profiles:
active: '@environment@' #注意YAML配置文件需要加单引号,否则会报错

其他常用框架

邮件发送模块

导入封装好的邮件模块:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>

配置smtp服务器:

1
2
3
4
5
6
7
8
spring:
mail:
# 163邮箱的地址为smtp.163.com,直接填写即可
host: smtp.163.com
# 你申请的163邮箱
username: javastudy111@163.com
# 注意密码是在开启smtp/pop3时自动生成的,记得保存一下,不然就找不到了
password: AZJTOAWZESLMHTNI

使用SimpleMailMessage发送简单邮件:

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
@SpringBootTest
class SpringBootTestApplicationTests {

//JavaMailSender是专门用于发送邮件的对象,自动配置类已经提供了Bean
@Autowired
JavaMailSender sender;

@Test
void contextLoads() {
//SimpleMailMessage是一个比较简易的邮件封装,支持设置一些比较简单内容
SimpleMailMessage message = new SimpleMailMessage();
//设置邮件标题
message.setSubject("【电子科技大学教务处】关于近期学校对您的处分决定");
//设置邮件内容
message.setText("XXX同学您好,经监控和教务巡查发现,您近期存在旷课、迟到、早退、上课刷抖音行为," +
"现已通知相关辅导员,请手写5000字书面检讨,并在2022年4月1日17点前交到辅导员办公室。");
//设置邮件发送给谁,可以多个,这里就发给你的QQ邮箱
message.setTo("你的QQ号@qq.com");
//邮件发送者,这里要与配置文件中的保持一致
message.setFrom("javastudy111@163.com");
//OK,万事俱备只欠发送
sender.send(message);
}

}

使用MimeMessageHelper实现添加附件等更多功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
@Test
void contextLoads() throws MessagingException {
//创建一个MimeMessage
MimeMessage message = sender.createMimeMessage();
//使用MimeMessageHelper来帮我们修改MimeMessage中的信息
MimeMessageHelper helper = new MimeMessageHelper(message, true);
helper.setSubject("Test");
helper.setText("lbwnb");
helper.setTo("你的QQ号@qq.com");
helper.setFrom("javastudy111@163.com");
//发送修改好的MimeMessage
sender.send(message);
}

接口规则校验

导入接口校验框架:

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

使用注解实现接口校验:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Slf4j
@Validated //首先在Controller上开启接口校验
@Controller
public class TestController {

...

@ResponseBody
@PostMapping("/submit")
public String submit(@Length(min = 3) String username, //使用@Length注解一步到位
@Length(min = 10) String password){
System.out.println(username.substring(3));
System.out.println(password.substring(2, 10));
return "请求成功!";
}
}

处理异常:

1
2
3
4
5
6
7
8
9
@ControllerAdvice
public class ValidationController {

@ResponseBody
@ExceptionHandler(ConstraintViolationException.class)
public String error(ValidationException e){
return e.getMessage(); //出现异常直接返回消息
}
}

对于对象类型:

1
2
3
4
5
6
7
@Data
public class Account {
@Length(min = 3) //只需要在对应的字段上添加校验的注解即可
String username;
@Length(min = 10)
String password;
}
1
2
3
4
5
6
7
@ResponseBody
@PostMapping("/submit") //在参数上添加@Valid注解表示需要验证
public String submit(@Valid Account account){
System.out.println(account.getUsername().substring(3));
System.out.println(account.getPassword().substring(2, 10));
return "请求成功!";
}

异常处理:

1
2
3
4
5
6
7
8
9
10
11
@ResponseBody
@ExceptionHandler({ConstraintViolationException.class, MethodArgumentNotValidException.class})
public String error(Exception e){
if(e instanceof ConstraintViolationException exception) {
return exception.getMessage();
} else if(e instanceof MethodArgumentNotValidException exception){
if (exception.getFieldError() == null) return "未知错误";
return exception.getFieldError().getDefaultMessage();
}
return "未知错误";
}

接口文档生成

使用Swagger,导入依赖:

1
2
3
4
5
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.1.0</version>
</dependency>

配置文档描述信息:

1
2
3
4
5
6
7
8
9
@Bean
public OpenAPI springDocOpenAPI() {
return new OpenAPI().info(new Info()
.title("图书管理系统 - 在线API接口文档") //设置API文档网站标题
.description("这是一个图书管理系统的后端API文档,欢迎前端人员查阅!") //网站介绍
.version("2.0") //当前API版本
.license(new License().name("我的B站个人主页") //遵循的协议,这里拿来写其他的也行
.url("https://space.bilibili.com/37737161")));
}

为Controller编写API信息:

1
2
3
4
5
//使用@Tag注解来添加Controller描述信息
@Tag(name = "账户验证相关", description = "包括用户登录、注册、验证码请求等操作。")
public class TestController {
...
}

添加请求映射配置描述信息:

1
2
3
4
5
6
7
8
9
10
11
@ApiResponses({
@ApiResponse(responseCode = "200", description = "测试成功"),
@ApiResponse(responseCode = "500", description = "测试失败") //不同返回状态码描述
})
@Operation(summary = "请求用户数据测试接口") //接口功能描述
@ResponseBody
@GetMapping("/hello")
//请求参数描述和样例
public String hello(@Parameter(description = "测试文本数据", example = "KFCvivo50") @RequestParam String text) {
return "Hello World";
}

隐藏接口:

1
2
3
4
5
6
@Hidden
@ResponseBody
@GetMapping("/hello")
public String hello() {
return "Hello World";
}

实体类文档:

1
2
3
4
5
6
7
8
9
10
11
12
@Data
@Schema(description = "用户信息实体类")
public class User {
@Schema(description = "用户编号")
int id;
@Schema(description = "用户名称")
String name;
@Schema(description = "用户邮箱")
String email;
@Schema(description = "用户密码")
String password;
}

在生成环境关闭文档:

1
2
3
springdoc:
api-docs:
enabled: false