普通视图
一文读懂!线上线下陪玩系统小程序源码的神奇力量
Nest如何连接数据库
前端视角 Java Web 入门手册 5.3:真实世界 Web 开发——RESTful API 与 Spring MVC
前端视角 Java Web 入门手册 5.2:真实世界 Web 开发——Spring Boot 应用启动流程
1. 概述
Spring Boot 通过简化 Spring 应用的配置和部署,极大地加快了开发速度。启动一个 Spring Boot Web应用涉及多个步骤,从引导应用到监听和处理 HTTP 请求。依赖注入作为 Spring 框架的核心特性,在应用启动和运行中起到了至关重要的作用
2. 启动流程的关键步骤
2.1 main()
方法与 SpringApplication.run()
入口点:Spring Boot应用的启动从包含 main()
方法的主类开始。该方法调用 SpringApplication.run()
,这是启动整个Spring Boot应用的关键步骤
@SpringBootApplication
public class MySpringBootApp {
public static void main(String[] args) {
SpringApplication.run(MySpringBootApp.class, args);
}
}
-
@SpringBootApplication
:这是一个复合注解,包含了 @Configuration、@EnableAutoConfiguration 和 @ComponentScan -
SpringApplication.run()
:启动Spring Boot应用,创建并刷新应用上下文
2.2 创建应用上下文(ApplicationContext)
SpringApplication.run()
方法的核心职责之一是创建 应用上下文(ApplicationContext) ,这是Spring应用的核心容器,负责管理和配置应用中的所有Beans。
步骤:
- 初始化Spring应用:确定应用类型
-
创建
ApplicationContext
:具体实现通常是AnnotationConfigServletWebServerApplicationContext
,适用于基于注解的配置和Servlet Web服务器 -
加载配置类:解析
@SpringBootApplication
和其他配置注解,加载 Bean 定义
2.3 自动配置(Auto-Configuration)
Spring Boot 的自动配置功能通过推断项目所需要的配置,自动配置Spring应用,减少大量繁琐的手动设置
工作原理:
-
条件注解:如
@ConditionalOnClass
、@ConditionalOnMissingBean
,根据特定条件决定是否应用某个配置 -
配置类加载:
spring.factories
文件中列出的自动配置类被加载并应用
@Configuration
@ConditionalOnClass(name = "org.springframework.web.servlet.DispatcherServlet")
public class WebMvcAutoConfiguration {
// 自动配置Web MVC相关的Bean
}
优点:
- 简化配置:自动配置常用组件,如数据源、MVC、模板引擎等
- 可扩展性:开发者可以通过覆盖默认配置或定义新的配置类来自定义应用
2.4 组件扫描与Bean的创建
Spring Boot 通过 组件扫描(Component Scanning) 自动发现和注册 Beans。所有被注解标记的类(如 @Component
、@Service
、@Repository
、@Controller
等)都会被Spring容器管理
步骤:
- 启动组件扫描:位于主类所在的包及其子包
- 识别候选组件:扫描带有特定注解的类
- 创建Bean实例:根据依赖注入的规则创建和初始化 Bean
@Service
public class GreetingService {
public String greet() {
return "Hello, Spring Boot!";
}
}
@RestController
public class GreetingController {
private final GreetingService greetingService;
@Autowired // 自动注入GreetingService
public GreetingController(GreetingService greetingService) {
this.greetingService = greetingService;
}
@GetMapping("/greet")
public String greet() {
return greetingService.greet();
}
}
2.5 依赖注入(Dependency Injection, DI)详解
依赖注入是 Spring 框架的核心特性之一,它通过外部化对象的依赖关系,降低了代码的耦合度,提高了模块的可测试性和可维护性。在 Spring Boot 应用的启动过程中,依赖注入起到了至关重要的作用
2.5.1 依赖注入的原理
依赖注入遵循 控制反转(Inversion of Control, IoC) 的原则,即对象不再自行创建或查找其依赖,而是由外部容器(如 Spring 的 ApplicationContext)负责注入所需的依赖
核心概念:
- IoC容器:Spring 的 ApplicationContext 即为 IoC 容器,负责管理Bean的生命周期和依赖关系
- Bean:由 Spring 容器管理的对象
- 依赖:Bean 所需要的其它 Bean 或资源
2.5.2 依赖注入的方式
Spring 支持多种依赖注入方式,主要包括:
- 构造器注入(Constructor Injection) :通过构造函数注入依赖,推荐使用
- Setter注入(Setter Injection) :通过 Setter 方法注入依赖
-
字段注入(Field Injection) :直接在字段上使用
@Autowired
注解注入依赖,不推荐使用,因为不利于测试和可维护性
- 构造器注入:
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 业务逻辑方法
}
- Setter注入:
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 业务逻辑方法
}
- 字段注入(不推荐):
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 业务逻辑方法
}
2.5.3 Bean 的生命周期与依赖注入
在 Spring Boot 应用启动过程中,Beans 的创建和依赖注入遵循一定的生命周期:
- 实例化(Instantiation) :Spring 容器根据 Bean 定义创建 Bean 的实例
- 填充属性(Populate Properties) :注入 Bean 的依赖
-
调用初始化方法(Initialization) :执行Bean的初始化逻辑,如实现
InitializingBean
接口的afterPropertiesSet()
方法,或使用@PostConstruct
注解的方法 - 就绪使用(Ready to Use) :Bean 已准备好被应用程序使用
-
销毁(Destruction) :应用关闭时,执行Bean的销毁逻辑,如实现
DisposableBean
接口的destroy()
方法,或使用@PreDestroy
注解的方法
@Service
public class ExampleService implements InitializingBean, DisposableBean {
@Autowired
private AnotherService anotherService;
@Override
public void afterPropertiesSet() throws Exception {
// 初始化逻辑
}
@Override
public void destroy() throws Exception {
// 销毁逻辑
}
}
使用 @PostConstruct
和 @PreDestroy
注解:
@Service
public class ExampleService {
@Autowired
private AnotherService anotherService;
@PostConstruct
public void init() {
// 初始化逻辑
}
@PreDestroy
public void cleanup() {
// 销毁逻辑
}
}
2.5.4 依赖注入在启动流程中的作用
在 Spring Boot Web 应用的启动过程中,依赖注入涉及以下几个关键步骤:
-
组件扫描:Spring扫描指定包下的所有类,识别带有注解(如
@Component
、@Service
、@Repository
、@Controller
等)的 Bean - 创建Bean实例:根据扫描到的Bean定义,Spring创建Bean的实例。
- 解析依赖关系:Spring 识别 Bean 之间的依赖关系,并根据依赖注入方式(构造器、Setter、字段)注入所需的依赖
- 初始化Bean:执行 Bean 的初始化方法,完成 Bean 的准备工作
- 注册Bean到容器:将 Bean 注册到 ApplicationContext 中,供其它组件使用
假设有以下组件:
-
UserRepository:数据访问层接口,继承自
JpaRepository
-
UserService:服务层,依赖
UserRepository
-
UserController:控制器,依赖
UserService
// UserRepository.java
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// 自定义查询方法
}
// UserService.java
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public List<User> getAllUsers() {
return userRepository.findAll();
}
// 其他业务逻辑方法
}
// UserController.java
@RestController
@RequestMapping("/users")
public class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping
public List<User> getAllUsers() {
return userService.getAllUsers();
}
// 其他API端点
}
启动流程中的依赖注入:
- 组件扫描:Spring 扫描 com.example.hellospring 及其子包,发现三个 Bean:UserRepository、UserService、UserController
- 创建 UserRepository 实例:Spring 根据接口创建动态代理实例,并注入到容器中
- 创建 UserService 实例:Spring 识别 UserService 构造器中的 UserRepository 依赖,并注入 UserRepository 实例
- 创建 UserController 实例:Spring识别 UserController 构造器中的 UserService 依赖,并注入 UserService 实例
-
初始化和注册:
- 所有 Bean 的初始化方法被调用,完成 Bean 的配置和准备
- Bean 被注册到
ApplicationContext
中,供应用程序使用
这样通过依赖注入,Spring Boot 确保各个组件之间的耦合度低,且责任清晰,便于测试和维护
2.6 设置嵌入式服务器(Embedded Server)
对于 Web 应用,Spring Boot 通常使用嵌入式服务器(如Tomcat、Jetty 或 Undertow)来运行应用,避免了传统的部署方式
-
解析依赖:如
spring-boot-starter-web
会引入 Tomcat 依赖 - 配置服务器:根据配置文件和自动配置设置服务器参数
- 创建服务器实例:创建一个 Tomcat 服务器,并配置端口(默认8080)
2.7 启动嵌入式服务器并监听请求
一旦嵌入式服务器被配置和创建,它会被启动并开始监听指定端口的 HTTP 请求
- 初始化服务器:启动 Tomcat 容器
- 部署应用:将 Spring 应用部署到服务器中,注册 Servlet、过滤器等
- 开始监听:服务器开始接受并处理来自客户端的 HTTP 请求
2.8 请求处理流程
当服务器接收到 HTTP 请求时,以下步骤会被执行:
- DispatcherServlet 接收请求:作为前端控制器,负责分发请求到具体的处理器
- 获取 Handler:DispatcherServlet 通过 HandlerMapping 找到对应的 Controller 方法
- 调用 Controller 方法:执行业务逻辑,通常涉及服务层和数据访问层
- 返回响应:将结果打包成 HTTP 响应,并通过 DispatcherServlet 发送回客户端
处理流程:
- 请求被 DispatcherServlet 接收
-
HandlerMapping 找到
GreetingController.greet()
方法 -
调用
greet()
方法,返回 "Hello, Spring Boot!" - DispatcherServlet 将响应返回给客户端
3. 启动过程中的关键类与组件
理解 Spring Boot 启动过程的关键类和组件有助于深入了解其工作机制。以下是一些重要的类和组件:
-
SpringApplication
:核心类,用于启动 Spring Boot 应用。配置应用上下文,触发自动配置等 -
ApplicationContext
:Spring 的 IoC 容器,管理和配置应用中的所有 Beans -
AutoConfiguration
:自动配置类,基于项目依赖和配置自动配置 Spring 组件 -
DispatcherServlet
:Spring MVC 的核心 Servlet,负责处理和分发 HTTP 请求 -
EmbeddedServletContainerFactory
:用于创建嵌入式服务器实例的工厂类 -
BeanFactory
和BeanDefinition
:底层接口和类,定义和管理Bean的创建与注入 -
Environment
:封装了应用的环境信息,如配置属性、系统属性等 -
Banner
:Spring Boot 启动时显示的横幅,可以自定义或关闭
4. 启动流程图
Spring Boot Web 应用的启动流程图大致如下,可以更直观地理解整个过程:
+--------------------+
| main() 方法 |
| (调用 SpringApplication.run()) |
+---------+----------+
|
v
+---------+----------+
| SpringApplication |
| 初始化 |
+---------+----------+
|
v
+---------+----------+
| 创建 ApplicationContext |
| (IoC 容器) |
+---------+----------+
|
v
+---------+----------+
| 自动配置 Auto-Configuration |
| (根据依赖和配置) |
+---------+----------+
|
v
+---------+----------+
| 组件扫描与Bean创建 |
| @Component, @Service, etc. |
+---------+----------+
|
v
+---------+----------+
| 依赖注入(DI) |
| 注入Bean依赖 |
+---------+----------+
|
v
+---------+----------+
| 设置嵌入式服务器 |
| (Tomcat, Jetty, etc.)|
+---------+----------+
|
v
+---------+----------+
| 启动嵌入式服务器并监听请求 |
+---------+----------+
|
v
+---------+----------+
| 处理HTTP请求 |
| DispatcherServlet -> Controllers |
+--------------------+
5. 总结
通过深入了解 Spring Boot Web 应用的启动流程,特别是依赖注入的部分,可以更好地理解其工作原理,从而更有效地开发和调试应用:
-
入口点:应用启动从
main()
方法开始,调用SpringApplication.run()
-
应用上下文:通过
ApplicationContext
管理和配置所有 Beans,实现依赖注入和 IoC - 自动配置:根据项目依赖和配置自动配置 Spring 组件,简化开发过程
- 组件扫描:自动发现和注册带有特定注解的 Bean,支持依赖注入
- 依赖注入:通过构造器、Setter 或字段注入方式,管理 Bean 之间的依赖关系
- 嵌入式服务器:内置服务器(Tomcat)使应用可独立运行,简化部署
- 请求处理:DispatcherServlet 作为前端控制器,负责分发和处理 HTTP 请求
前端视角 Java Web 入门手册 5.1:真实世界 Web 开发——初识 Spring Boot
Spring Framework 是一个开源的、功能强大的 Java框架,旨在简化企业级 Java开发。它通过提供全面的基础设施支持,使开发者能够专注于业务逻辑的实现。Spring 框架由多个模块组成,如 Spring Core、Spring MVC、Spring Data、Spring Security等。开发者可以根据项目需求,选择性地引入和使用这些模块,构建灵活且可扩展的应用。
虽然 Spring 功能强大,但其配置和设置过程可能繁琐。Spring Boot 建立在 Spring Framework 之上,简化了 Spring 应用的配置和部署。它并不是另一个框架,而是一个增强Spring Framework的配置和启动工具。
Spring 和 SpringBoot 的关系有点类似于 Node.js 中 Koa 与 Egg.js 的关系,Spring 和 Koa 都是基础性的框架,提供了核心功能,但需要更多定制;Spring Boot 和 Egg.js 在各自的基础框架之上进行了增强,提供了更多的预配置和自动化工具,帮助开发者快速上手并提高效率。
使用 Spring Initializr 创建 SpringBoot 项目
Spring Initializr 是一个在线工具,用于生成Spring Boot项目的基础结构
点击 Generate
按钮,下载生成的项目压缩包并解压,即可得到如下的项目结构
hellospring
├── src
│ ├── main
│ │ ├── java
│ │ │ └── com.example.hellospring
│ │ │ ├── HellospringApplication.java
│ │ │ └── controller
│ │ │ └── HelloController.java
│ │ └── resources
│ │ ├── application.properties
│ │ └── static
│ │ └── ...
│ └── test
│ └── java
│ └── com.example.hellospring
│ └── HellospringApplicationTests.java
├── mvnw
├── mvnw.cmd
├── pom.xml
└── README.md
- src/main/java:Java 源代码目录
- src/main/resources:资源文件目录,如配置文件、静态资源等
- pom.xml:Maven 项目配置文件
- mvnw & mvnw.cmd:Maven Wrapper 脚本,确保团队使用相同版本的 Maven
Controller
既然是 Web 应用请求自然先到 Controller,Controller 负责处理 HTTP 请求,它们接收请求,调用相应的服务,并返回响应
// src/main/java/com/example/hellospring/controller/HelloController.java
package com.example.hellospring.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
@RestController 用于将类标记为 Spring MVC 控制器,并自动将控制器中的方法返回的对象序列化为 JSON 或 XML 格式的响应体,它是 @Controller 和 @ResponseBody 注解的组合
- @Controller: 标记一个类作为控制器,处理 HTTP 请求
- @ResponseBody: 指示控制器方法的返回值应该直接写入 HTTP 响应体,而不是返回一个视图
@GetMapping 是@RequestMapping(method = RequestMethod.GET)
的简写,用来处理 HTTP GET 请求。sayHello 方法使用 @GetMapping("/hello") 注解,这意味着该方法会处理 /hello
的 GET 请求
通过这些注解,Spring 提供了直观和简洁的方法来定义控制器的请求映射和响应处理,大大简化了开发 RESTful 服务的工作
构建一个简单的 REST API
为了更好地理解 Spring Boot 的工作机制,通过一个简单的示例项目,构建一个 RESTful API,实现用户的 CRUD 操作
创建文件
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── com
│ │ └── example
│ │ └── hellospring
│ │ ├── HellospringApplication.java
│ │ ├── controller
│ │ │ └── UserController.java
│ │ ├── model
│ │ │ └── User.java
│ │ └── repository
│ │ └── UserRepository.java
│ └── resources
│ ├── application.properties
│ ├── static
│ └── templates
└── test
添加必要依赖
在 pom.xml
添加依赖
<!-- Spring Boot Starter Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- H2 Database -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
-
spring-boot-starter-web:用于快速启动和构建基于 Spring MVC 的 Web 应用程序。这个 Starter 包含了构建 Web 应用程序所需的常用依赖和配置,简化了开发过程
- Spring MVC:提供构建 Web 应用的基础架构,支持 MVC 架构设计模式,帮助开发者创建 Web 控制器、服务和 View 层
- Embedded Servers:自带嵌入式服务器(如 Tomcat、Jetty、Undertow),使应用可以独立运行,不需要额外安装外部服务器
- RESTful Services:支持创建 RESTful 风格的 Web 服务和 API,非常适合构建轻量级服务
- JSON 处理:默认集成 Jackson 库,用于处理 JSON 数据的序列化和反序列化
- 数据验证:支持使用 Java Bean Validation API 进行数据验证
-
内容协商:提供内容协商机制,可以根据客户端请求的
Accept
头返回不同格式(如 JSON、XML)的响应
- spring-boot-starter-data-jpa:用于简化基于 Java Persistence API (JPA) 的数据访问层开发,它集成了 Spring Data JPA 和 Hibernate ORM 等常用组件,使得与数据库的交互更加简单高效
- com.h2database:是 Maven 依赖的一个组 ID,对应的是 H2 数据库,H2 是一种轻量级的嵌入式关系型数据库。H2 数据库因为其小巧、易于使用以及内存模式的支持,常常被用作开发、测试阶段的内存数据库
定义 Entity
在 Java 的持久化领域中,Entity
是一个非常重要的概念。实体类用来表示一个数据库表。每个实体类的实例,即一个对象,通常对应数据库表中的一行记录
-
@Entity
:表明该类是一个实体,需要持久化 -
@Table
:用于指定实体类对应的数据库表名,如果没有这个注解,默认表名是实体类的名字 -
@Id
:指定实体的主键字段 -
@Column
:用于指定实体类的某个字段对应于数据库表的特定列
实体类需要一个无参数构造函数,以便 JPA 提供的工具来构造此对象的实例
// src/main/java/com/example/hellospring/model/User.java
package com.example.hellospring.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) // 主键的生成策略
private Long id;
private String name;
private String email;
// 构造器
public User() {}
public User(String name, String email) {
this.name = name;
this.email = email;
}
// Getters 和 Setters
public Long getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
// toString 方法(可选)
@Override
public String toString() {
return "User{id=" + id + ", name='" + name + "', email='" + email + "'}";
}
}
创建 Repository
Repository 接口抽象化数据访问层,负责与数据库进行交互,执行 CRUD 操作,Spring Data JPA 自动生成实现类,简化数据访问逻辑
-
CrudRepository
:定义了一些通用的 CRUD 操作方法。如 save()、findById()、findAll()、deleteById() 等 -
JpaRepository
:继承自 CrudRepository,提供了更多 JPA 相关的功能,例如批量操作 -
PagingAndSortingRepository
:扩展自 CrudRepository,添加了分页和排序功能的方法
// src/main/java/com/example/hellospring/repository/UserRepository.java
package com.example.hellospring.repository;
import com.example.hellospring.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
// 可以在这里定义自定义查询方法
}
编写 Controller
在传统的 Java 编程中,一个类依赖于另一个类时,通常需要明确地创建依赖对象,而在 Spring 中,框架自动决定类中依赖的对象,并创建和注入这些对象,这个过程被称为自动装配。
@Autowired
用于实现自动装配,告诉 Spring 要在上下文中找到被标注的依赖类型的 Bean,并将其注入到注解所在的位置
// src/main/java/com/example/hellospring/controller/UserController.java
package com.example.hellospring.controller;
import com.example.hellospring.model.User;
import com.example.hellospring.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/users")
public class UserController {
private final UserRepository userRepository;
@Autowired
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
// 创建用户
@PostMapping
public User createUser(@RequestBody User user) {
return userRepository.save(user);
}
// 获取所有用户
@GetMapping
public List<User> getAllUsers() {
return userRepository.findAll();
}
// 根据ID获取用户
@GetMapping("/{id}")
public User getUserById(@PathVariable Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found"));
}
// 更新用户
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User updatedUser) {
return userRepository.findById(id)
.map(user -> {
user.setName(updatedUser.getName());
user.setEmail(updatedUser.getEmail());
return userRepository.save(user);
})
.orElseThrow(() -> new RuntimeException("User not found"));
}
// 删除用户
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userRepository.deleteById(id);
}
}
配置数据库访问
application.properties 或 application.yml 用于配置应用的各种参数,如数据库连接、服务器端口等
# src/main/resources/application.properties
spring.application.name=hellospring
# Server Configuration
server.port=8080
# H2 Database Configuration (内存型数据库,方便测试)
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update
# H2 Console Configuration
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
项目启动后可以通过 http://localhost:8080/h2-console 可视化访问数据库
测试
创建用户
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"name":"Alice","email":"alice@example.com"}'
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie","email":"charlie@example.com"}'
获取所有用户
curl -X GET http://localhost:8080/users
获取单个用户
curl -X GET http://localhost:8080/users/2
更新用户
curl -X PUT http://localhost:8080/users/1 \
-H "Content-Type: application/json" \
-d '{"name":"Alice Smith","email":"alice.smith@example.com"}'
删除用户
curl -X DELETE http://localhost:8080/users/1
自动化构建与热部署
Spring Boot DevTools 提供了自动重启和热部署功能,类似于前端的热模块替换(HMR),可以大幅提升开发效率
<!-- pom.xml -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
为了避免在服务环境启用,可以在 pom.xml
的 build
部分添加以下配置
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludeDevtools>true</excludeDevtools>
</configuration>
</plugin>
</plugins>
</build>
如果使用 IntelliJ IDEA 还需要做几个设置