Article

Spring Boot文档

更新于:2026-07-15

第一章:Spring Boot 入门与环境搭建

1.1 Spring Boot 简介与核心特性

概念名称说明注意事项
Spring Boot一个用于快速构建基于 Spring 的生产级应用的框架,通过”约定优于配置”理念简化开发流程。不是 Spring 的替代品,而是其增强工具,用于减少样板代码和配置。
自动配置(Auto-configuration)根据项目依赖自动配置 Spring 和第三方库的 Bean。例如,引入 spring-boot-starter-web 后自动配置嵌入式 Tomcat 和 MVC。可通过 @EnableAutoConfiguration(exclude = {...}) 排除不需要的配置。
起步依赖(Starter Dependencies)预定义的依赖组合,简化 Maven/Gradle 配置。如 spring-boot-starter-web 包含 Web 开发所需全部依赖。避免手动添加重复依赖,优先使用 Starter。
嵌入式服务器内置 Tomcat、Jetty 或 Undertow,无需部署 WAR 到外部容器,直接运行 JAR。默认使用 Tomcat;可通过排除依赖更换为 Jetty 或 Undertow。
Actuator提供生产环境监控和管理功能(如健康检查、指标、环境信息等)。生产环境需配置安全访问控制,避免信息泄露。
无代码生成与 XML 配置基于 Java 注解和自动配置,无需生成代码或编写大量 XML。仍支持 XML 配置,但推荐使用注解方式。

1.2 开发环境准备(JDK、Maven/Gradle、IDE)

工具/环境版本要求用途安装与配置说明注意事项
JDK8 或以上(推荐 17 或 21)Java 运行环境安装后设置 JAVA_HOME 环境变量,并将 bin 目录加入 PATH。Spring Boot 3.x 要求 JDK 17+。
Apache Maven3.5 或以上项目构建与依赖管理下载解压,配置 MAVEN_HOME 和 PATH,修改 settings.xml 设置仓库镜像(如阿里云)。推荐使用国内镜像加速依赖下载。
Gradle6.8 或以上替代 Maven 的构建工具安装后配置 GRADLE_HOME 和 PATH,或使用 Wrapper(gradlew)。Gradle 脚本更灵活,但学习成本略高。
IDEIntelliJ IDEA / Eclipse / Spring Tool Suite (STS)代码编写与调试推荐使用 IDEA 或 STS,内置 Spring Boot 支持。安装 Lombok 插件以支持注解处理器。

1.3 创建第一个 Spring Boot 项目(使用 Spring Initializr)

步骤操作说明注意事项
1. 访问 Initializr打开 https://start.spring.io官方项目生成器,支持 Web 和 IDE 集成。可选择 Maven 或 Gradle 构建方式。
2. 选择项目元数据填写 Group(如 com.example)、Artifact(如 demo)、Name、Description、Package 名称定义项目的坐标和包结构。Package 名称决定项目根包路径。
3. 选择 Spring Boot 版本推荐选择最新稳定版(如 3.3.x)版本影响依赖兼容性。若需 JDK 8,应选择 Spring Boot 2.7.x。
4. 添加依赖至少选择 Spring Web添加 Web 开发支持(内含 Tomcat + Spring MVC)。可同时添加 Lombok、Actuator、Spring Data JPA 等。
5. 生成项目点击 “Generate” 下载 ZIP 包解压后导入 IDE。解压路径避免中文或空格。
6. 导入 IDE使用 IDEA 或 Eclipse 打开项目Maven 会自动下载依赖。首次导入可能耗时较长,请耐心等待。

1.4 项目结构解析与核心配置文件

目录/文件路径用途注意事项
src/main/javaJava 源码目录存放所有 Java 类文件。主启动类默认在此目录下。
src/main/resources资源文件目录存放配置文件、静态资源、模板等。application.propertiesapplication.yml 必须在此目录。
src/test/java测试代码目录存放单元测试和集成测试类。测试类通常与主类结构对应。
pom.xml项目根目录Maven 构建配置文件,定义依赖、插件、版本等。不要手动修改依赖版本,除非明确需要。
application.propertiessrc/main/resources主配置文件,键值对格式。优先级低于 application.yml(若同时存在)。
application.ymlsrc/main/resourcesYAML 格式配置文件,结构更清晰。缩进敏感,必须使用空格,不能用 Tab。
staticsrc/main/resources/static存放静态资源(CSS、JS、图片等)。可通过 HTTP 直接访问,如 /js/app.js
templatessrc/main/resources/templates存放模板文件(Thymeleaf、Freemarker 等)。用于服务端渲染页面。

1.5 启动类与自动配置原理简介

概念语法用途代码示例注意事项
@SpringBootApplication@SpringBootApplication组合注解,启用自动配置、组件扫描和配置类功能。@SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }必须放在根包下,以便扫描所有子包组件。
SpringApplication.run()SpringApplication.run(Application.class, args)启动 Spring Boot 应用,初始化 IoC 容器。同上返回 ApplicationContext 对象,可用于获取 Bean。
自动配置原理@EnableAutoConfiguration + spring.factoriesSpring Boot 启动时扫描 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件,加载自动配置类。无需手动编写配置类使用 @ConditionalOnXXX 控制生效条件。
组件扫描@ComponentScan(包含在 @SpringBootApplication 中)自动发现并注册标注了 @Component@Service 等的类为 Bean。默认扫描启动类所在包及其子包可通过 basePackages 指定扫描路径。

第二章:核心配置与属性管理

2.1 application.properties 与 application.yml 基础语法

配置类型语法格式用途示例注意事项
properties 键值对key=value定义单个配置项server.port=8080
spring.application.name=myapp
不支持层级结构,重复键会覆盖。
YAML 对象结构key:
subkey: value
表示层级结构,更易读server:
port: 8080
spring:
application:
name: myapp
缩进必须使用空格,层级对齐。
YAML 数组key:
- item1
- item2
定义列表类型配置spring.profiles.active:
- dev
- db
列表项前用 - 和空格。
占位符引用${key:default}引用其他属性值,支持默认值server.port=${PORT:8080}常用于环境变量注入。
多文档块(YAML)---分隔多个独立文档spring:
profiles: dev
datasource:
url: jdbc:h2:mem:dev
---
spring:
profiles: prod
datasource:
url: jdbc:mysql://prod-db
用于多 Profile 配置。

2.2 自定义配置属性绑定(@ConfigurationProperties)

方法/注解语法用途代码示例注意事项
@ConfigurationProperties@ConfigurationProperties(prefix = "custom")将配置文件中以指定前缀开头的属性绑定到 Java Bean。@Component @ConfigurationProperties(prefix = "app") public class AppProperties { private String name; private int timeout; // getter/setter }必须提供 setter 方法(或使用构造函数绑定)。
@EnableConfigurationProperties@EnableConfigurationProperties(AppProperties.class)启用配置属性绑定功能,注册为 Bean。添加在启动类或配置类上若使用 @Component,则无需此注解。
松散绑定(Relaxed Binding)支持 kebab-casesnake_casecamelCase配置名与字段名不完全一致时自动匹配app.my-property 对应 myProperty 字段推荐使用 kebab-case 在配置文件中。
类型安全支持基本类型、集合、嵌套对象提供编译时类型检查可绑定 ListMap<String, String>集合建议使用 List 而非数组。

2.3 多环境配置(Profile)管理

方法语法用途代码示例注意事项
Profile 配置文件命名application-{profile}.properties/yml为不同环境提供独立配置。application-dev.yml
application-prod.yml
主文件 application.yml 为默认配置。
激活 Profilespring.profiles.active=dev指定当前激活的环境。application.yml 中:spring:
profiles:
active: dev
可同时激活多个,用逗号分隔。
@Profile@Profile("dev")注解方式控制 Bean 在特定环境下注册。@Configuration @Profile("dev") public class DevConfig { ... }可用于类或方法级别。
环境变量激活JAVA_OPTS=-Dspring.profiles.active=prod通过命令行或环境变量设置。java -jar app.jar --spring.profiles.active=test优先级高于配置文件。
Profile 分组spring.profiles.group.dev=dev,common将多个 Profile 组合成逻辑组。spring:
profiles:
group:
dev: dev,common
Spring Boot 2.4+ 支持。

2.4 外部化配置优先级详解

配置来源优先级(从高到低)说明示例注意事项
命令行参数1最高优先级,可覆盖所有其他配置。java -jar app.jar --server.port=9090多个参数用空格分隔。
SPRING_APPLICATION_JSON2环境变量中内联 JSON 配置。export SPRING_APPLICATION_JSON='{"server":{"port":8080}}'适用于容器化部署。
ServletConfig 初始化参数3Servlet 容器级别的初始化参数。web.xml<init-param>较少使用。
JVM 系统属性4System.setProperty()-D 参数。-Dserver.port=8081
操作系统环境变量5系统级环境变量,支持下划线命名转换。SERVER_PORT=8082推荐使用大写下划线格式。
application-{profile}.yml6特定环境的配置文件。application-dev.yml
application.yml7主配置文件。application.yml
@PropertySource8注解方式加载的属性文件。@PropertySource("classpath:db.properties")优先级较低。
默认属性(通过 SpringApplication.setDefaultProperties9最低优先级,作为最终 fallback。SpringApplication app = new SpringApplication(App.class); app.setDefaultProperties(...);

2.5 配置加密与敏感信息处理(可选)

方法说明工具/库注意事项
环境变量存储将数据库密码等敏感信息通过环境变量注入。Docker secrets、K8s Secrets、CI/CD 环境变量避免硬编码在配置文件中。
Jasypt 加密使用 Jasypt-Spring Boot 实现配置项加解密。jasypt-spring-boot-starter需配置加密密码(PBE)和算法。
Spring Cloud Config + Vault集成 HashiCorp Vault 实现集中化密钥管理。spring-cloud-starter-vault-config适用于微服务架构。
AWS KMS / Azure Key Vault云平台提供的密钥管理服务。云厂商 SDK安全性高,适合云原生应用。
不提交敏感文件将包含敏感信息的配置文件加入 .gitignore.gitignoreapplication-prod.yml 不应提交到 Git。

第三章:Web 开发基础

3.1 Spring MVC 架构概述

概念说明注意事项
DispatcherServlet前端控制器,接收所有请求并分发到处理器。是 Spring MVC 的核心,由 Spring Boot 自动配置。
HandlerMapping根据请求 URL 查找对应的处理器(Controller 方法)。支持多种映射策略(如注解、XML)。
Controller处理具体业务逻辑,返回模型和视图或数据。使用 @Controller@RestController 注解。
ModelAndView封装模型数据和视图名(传统 MVC 模式)。在 REST API 中较少使用。
ViewResolver解析视图名,定位实际视图(如 JSP、Thymeleaf)。REST 场景下通常不需要。
Model用于在控制器和视图之间传递数据。可通过 ModelModelMapModelAndView 添加属性。
RESTful 支持@RestController 自动序列化返回对象为 JSON。结合 @ResponseBody 使用。

3.2 控制器开发(@Controller 与 @RestController)

注解语法用途代码示例注意事项
@Controller@Controller标识一个类为 Spring MVC 控制器,通常返回视图名。@Controller public class HomeController { @GetMapping("/") public String home(Model model) { model.addAttribute("msg", "Hello"); return "index"; } }需配合视图技术使用。
@RestController@RestController组合注解(@Controller + @ResponseBody),返回数据而非视图。@RestController public class ApiController { @GetMapping("/api") public Map<String, String> getData() { return Collections.singletonMap("data", "value"); } }默认所有方法返回 JSON/XML。
@ResponseBody@ResponseBody标注方法,表示返回值直接写入响应体。@Controller public class DataController { @GetMapping("/json") @ResponseBody public User getUser() { ... } }可用于单个方法,而非整个类。
@RequestBody@RequestBody将请求体 JSON 自动反序列化为 Java 对象。public ResponseEntity<?> createUser(@RequestBody User user) { ... }常用于 POST/PUT 请求。

3.3 请求映射(@RequestMapping 及其衍生注解)

注解语法用途代码示例注意事项
@RequestMapping@RequestMapping(value = "/users", method = RequestMethod.GET)通用映射,支持所有 HTTP 方法。@RequestMapping("/home") public String home() { ... }可标注类或方法。
@GetMapping@GetMapping("/users")映射 GET 请求。@GetMapping("/{id}") public User getUser(@PathVariable Long id) { ... }语义更清晰,推荐使用。
@PostMapping@PostMapping("/users")映射 POST 请求。@PostMapping public User createUser(@RequestBody User user) { ... }用于创建资源。
@PutMapping@PutMapping("/users/{id}")映射 PUT 请求。@PutMapping("/{id}") public User updateUser(@PathVariable Long id, @RequestBody User user) { ... }用于更新资源。
@DeleteMapping@DeleteMapping("/users/{id}")映射 DELETE 请求。@DeleteMapping("/{id}") public void deleteUser(@PathVariable Long id) { ... }用于删除资源。
@PatchMapping@PatchMapping("/users/{id}")映射 PATCH 请求(部分更新)。@PatchMapping("/{id}") public User partialUpdate(@PathVariable Long id, @RequestBody Map<String, Object> updates) { ... }不常用,但符合 REST 规范。

3.4 请求参数接收(@RequestParam、@PathVariable、@RequestBody)

注解语法用途代码示例注意事项
@RequestParam@RequestParam String name获取 URL 查询参数。@GetMapping("/search") public String search(@RequestParam String q) { ... }默认 required = true,可设 defaultValue
@RequestParam(required=false)@RequestParam(required = false)可选参数。@RequestParam(required = false, defaultValue = "1") int page若参数不存在,使用默认值。
@PathVariable@PathVariable Long id获取路径变量。@GetMapping("/{id}") public User get(@PathVariable Long id) { ... }路径变量名需与方法参数名一致,或使用 value 指定。
@RequestBody@RequestBody User user接收 JSON 请求体并反序列化。@PostMapping public User create(@RequestBody User user) { ... }需客户端设置 Content-Type: application/json
@RequestHeader@RequestHeader String userAgent获取请求头信息。@GetMapping("/info") public String getInfo(@RequestHeader("User-Agent") String agent) { ... }可用于鉴权、日志等。
@CookieValue@CookieValue("JSESSIONID") String sessionId获取 Cookie 值。@GetMapping("/cookie") public String readCookie(@CookieValue String sessionId) { ... }注意隐私与安全。

3.5 响应处理(@ResponseBody、ResponseEntity、视图解析)

方法/类型语法用途代码示例注意事项
@ResponseBody@ResponseBody(方法或类上)将返回值序列化为 JSON/XML 写入响应体。@ResponseBody @GetMapping("/data") public User getUser() { ... }@RestController 已隐含此注解。
ResponseEntityResponseEntity封装响应体、状态码、响应头,实现精细控制。@GetMapping("/{id}") public ResponseEntity getUser(@PathVariable Long id) { User user = service.findById(id); return ResponseEntity.ok(user); }推荐用于需要自定义状态码的场景。
返回 Stringreturn "index"返回视图名,由 ViewResolver 解析为页面。@Controller public String home() { return "home"; }仅适用于服务端渲染。
返回视图对象return new ModelAndView("view", model)同时指定视图和模型数据。@GetMapping("/mv") public ModelAndView show() { ModelAndView mv = new ModelAndView("page"); mv.addObject("key", "value"); return mv; }传统方式,REST 中不常用。
状态码设置ResponseEntity.status(HttpStatus.CREATED).body(data)自定义 HTTP 状态码。创建成功返回 201,无内容返回 204 等。遵循 REST 原则。

3.6 静态资源处理与 WebJars

资源类型默认路径用途访问方式注意事项
/staticsrc/main/resources/static存放通用静态资源(CSS、JS、图片)。http://localhost:8080/app.jsSpring Boot 自动映射。
/publicsrc/main/resources/public/static,优先级略低。同上可共存,/static 优先。
/resourcessrc/main/resources/resources传统资源目录。同上
/META-INF/resourcesJAR 内资源其他 JAR 包中的静态资源。自动暴露常用于 WebJars。
WebJars/webjars/{library}/{version}/file.js将前端库(如 jQuery、Bootstrap)打包为 JAR 管理。引入依赖后访问:/webjars/jquery/3.6.0/jquery.js简化前端依赖管理。
自定义静态路径spring.web.resources.static-locations=classpath:/custom/修改静态资源查找路径。可添加多个路径,逗号分隔。覆盖默认路径时需包含原有路径。

第四章:数据访问与持久化

4.1 Spring Data JPA 概述与基本概念

概念名称说明注意事项
Spring Data JPA提供了基于 JPA 的数据访问抽象层,简化了数据库操作。需要配置实体类和 Repository 接口。
JPAJava Persistence API,用于对象关系映射(ORM),将 Java 对象持久化到关系型数据库中。支持多种数据库,需正确配置 persistence.xml 或使用 Spring Boot 自动配置。
EntityManager管理实体的生命周期,执行 CRUD 操作。在 Spring Boot 中通常由框架自动管理,无需手动获取。
JPQLJava Persistence Query Language,面向对象查询语言,类似于 SQL 但操作的是实体对象而非表。不支持直接使用数据库函数,需通过原生查询实现。
Criteria API动态构建类型安全的查询。适合动态条件查询,但相比 JPQL 更复杂。
Transient, Persistent, Detached实体的状态:瞬时状态(未被持久化)、托管状态(已持久化且在事务中)、游离状态(已持久化但不在事务中)。正确理解状态转换对性能优化很重要。

4.2 实体类定义(@Entity、@Id、@GeneratedValue 等)

注解语法用途代码示例注意事项
@Entity@Entity标识一个类为实体类,对应数据库中的表。@Entity public class User { ... }类名默认作为表名,可通过 @Table 修改。
@Id@Id标识主键字段。@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;主键生成策略有多种,默认 AUTO。
@GeneratedValue@GeneratedValue(strategy = GenerationType.IDENTITY)定义主键生成策略(AUTO, IDENTITY, SEQUENCE, TABLE)。GenerationType.IDENTITY 适用于自增字段。使用 SEQUENCE 时需配置序列。
@Column@Column(name = "user_name", nullable = false)映射字段到列,可指定列名、长度、是否允许空等属性。@Column(nullable = false, length = 50) private String name;若字段名与列名一致,可省略 name 属性。
@Table@Table(name = "tbl_user")显式指定实体对应的表名。@Entity @Table(name = "tbl_user") public class User { ... }默认类名为表名,建议保持一致。
@Transient@Transient标记字段不进行持久化。@Transient private transient String tempData;临时字段,不会保存到数据库。

4.3 Repository 接口定义与方法命名规则

方法/注解语法用途代码示例注意事项
CrudRepositoryextends CrudRepository<T, ID>提供基本的 CRUD 操作接口。public interface UserRepository extends CrudRepository<User, Long> { }直接继承即可使用预定义方法。
PagingAndSortingRepositoryextends PagingAndSortingRepository<T, ID>继承 CrudRepository 并增加分页排序功能。public interface UserRepository extends PagingAndSortingRepository<User, Long> { }可实现分页和排序查询。
Repositoryextends Repository<T, ID>最基础的仓库接口,可定制化扩展。public interface CustomRepository extends Repository<User, Long> { }需自行定义具体方法。
方法命名规则findBy{PropertyName}根据实体属性自动生成查询方法。List findByName(String name);支持 AndOrBetweenLessThanGreaterThan 等关键字。
existsBy{PropertyName}boolean existsByName(String name);判断是否存在符合条件的记录。boolean existsByName(String name);返回布尔值,检查记录存在性。
countBy{PropertyName}long countByName(String name);计算符合条件的记录数。long countByName(String name);常用于统计。

4.4 自定义查询(@Query 注解)

方法/注解语法用途代码示例注意事项
@Query@Query("SELECT u FROM User u WHERE u.name = ?1")使用 JPQL 编写自定义查询。@Query("SELECT u FROM User u WHERE u.name = ?1") List findUsersByName(String name);参数从 1 开始编号,支持位置占位符。
@Param@Param("name") String name使用命名参数代替位置参数。@Query("SELECT u FROM User u WHERE u.name = :name") List findUsersByName(@Param("name") String name);命名参数更易读,推荐使用。
nativeQuery = true@Query(value = "SELECT * FROM users WHERE name = ?", nativeQuery = true)执行原生 SQL 查询。@Query(value = "SELECT * FROM users WHERE name = ?", nativeQuery = true) List findUsersByName(String name);需注意实体与表结构的一致性。
@Modifying@Modifying执行更新或删除操作。@Modifying @Query("UPDATE User u SET u.status = 'active' WHERE u.id = ?1") void activateUser(Long id);需结合 @Transactional 注解使用。

4.5 分页与排序(Pageable、Page)

方法/类型语法用途代码示例注意事项
PageablePageable pageable表示分页请求参数,包含页码、每页大小、排序信息。Page findAll(Pageable pageable);可使用 PageRequest.of(pageNumber, pageSize, Sort.by("field")) 创建实例。
PagePage封装分页结果,包含总记录数、当前页数据、是否有下一页等信息。Page page = userRepository.findAll(PageRequest.of(0, 10));总记录数通过额外查询获取,影响性能。
SortSort sort表示排序规则,可按多个字段排序。Sort sort = Sort.by(Sort.Direction.ASC, "name");复杂排序可通过 Sort.by() 链式调用。
PageRequest.of()PageRequest.of(int page, int size, Sort sort)创建分页请求对象。PageRequest.of(0, 10, Sort.by("age").descending());页码从 0 开始计数。
SliceSlice类似于 Page,但只返回当前页的数据,不提供总记录数。Slice slice = userRepository.findSlice(PageRequest.of(0, 10));更轻量,适合大数据集。

4.6 MyBatis 集成与使用(可选)

方法/注解语法用途代码示例注意事项
MyBatis-Spring-Boot-Starterorg.mybatis.spring.boot:mybatis-spring-boot-starter引入 MyBatis 支持,简化集成步骤。添加依赖后自动配置 Mapper 扫描。需配置 application.ymlapplication.properties
@MapperScan@MapperScan("com.example.mapper")指定扫描 Mapper 接口的包路径。@SpringBootApplication @MapperScan("com.example.mapper") public class Application { ... }可避免每个 Mapper 加 @Mapper 注解。
@Select@Select("SELECT * FROM users WHERE id = #{id}")定义查询语句。@Select("SELECT * FROM users WHERE id = #{id}") User getUserById(@Param("id") Integer id);使用 #{} 占位符传递参数。
@Insert@Insert("INSERT INTO users (name, age) VALUES (#{name}, #{age})")插入数据。@Insert("INSERT INTO users (name, age) VALUES (#{name}, #{age})") void insertUser(User user);注意事务管理。
@Update@Update("UPDATE users SET age = #{age} WHERE id = #{id}")更新数据。@Update("UPDATE users SET age = #{age} WHERE id = #{id}") void updateUserAge(@Param("id") Integer id, @Param("age") Integer age);更新操作可能影响多行,需谨慎处理。
@Delete@Delete("DELETE FROM users WHERE id = #{id}")删除数据。@Delete("DELETE FROM users WHERE id = #{id}") void deleteUserById(Integer id);删除前确认逻辑删除还是物理删除。

4.7 数据源配置与连接池管理

方法/属性语法用途示例注意事项
spring.datasource.urlspring.datasource.url=jdbc:mysql://localhost:3306/mydb配置数据库连接 URL。jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC注意时区设置,确保与服务器一致。
spring.datasource.usernamespring.datasource.username=root数据库用户名。root必填项,根据实际环境配置。
spring.datasource.passwordspring.datasource.password=password数据库密码。password考虑使用环境变量或加密存储。
spring.datasource.driver-class-namespring.datasource.driver-class-name=com.mysql.cj.jdbc.DriverJDBC 驱动类名。com.mysql.cj.jdbc.Driver根据使用的数据库选择正确的驱动。
HikariCPspring.datasource.hikari.maximum-pool-size=10配置连接池参数(HikariCP 是默认连接池)。maximum-pool-size 控制最大连接数。连接池参数对性能至关重要,需根据应用负载调整。
C3P0spring.datasource.type=com.mchange.v2.c3p0.ComboPooledDataSource使用其他连接池(如 C3P0)。需添加相应依赖并配置 spring.datasource.* 属性。不推荐,HikariCP 性能更优。
Druidspring.datasource.type=com.alibaba.druid.pool.DruidDataSource使用阿里开源的 Druid 连接池。需添加 druid-spring-boot-starter 依赖,并配置监控页面等高级功能。Druid 提供丰富的监控与安全特性。

第五章:RESTful API 设计与开发

5.1 REST 架构风格与设计原则

概念说明注意事项
REST(Representational State Transfer)一种基于 HTTP 协议的软件架构风格,用于设计网络应用程序的接口。不是协议或标准,而是一组约束和原则。
资源(Resource)系统中可被访问的数据实体,如用户、订单等,通过 URI 唯一标识。每个资源应有唯一的 URL,如 /users/1
统一接口(Uniform Interface)使用标准 HTTP 方法(GET、POST、PUT、DELETE)操作资源。遵循语义:GET 查询、POST 创建、PUT 更新、DELETE 删除。
无状态(Stateless)每个请求包含处理所需全部信息,服务器不保存客户端上下文。提高可伸缩性,但可能增加请求数据量。
表述性状态转移客户端通过获取资源的”表述”(如 JSON)来了解其当前状态,并通过操作改变服务器状态。响应应包含足够信息指导客户端下一步操作(HATEOAS 可选)。
HATEOAS(Hypermedia as the Engine of Application State)响应在返回数据的同时提供相关链接,驱动客户端状态迁移。如返回 { "id": 1, "name": "John", "links": [ { "rel": "self", "href": "/users/1" } ] }
URI 设计规范使用名词表示资源,避免动词;使用复数形式;层级清晰。推荐:/users, /users/1/orders;避免:/getUser, /deleteUser

5.2 使用 Spring Boot 构建 REST API

注解/组件语法用途代码示例注意事项
@RestController@RestController标识类为 REST 控制器,所有方法默认返回数据(JSON/XML)。等价于 @Controller + @ResponseBody
@RequestMapping@RequestMapping("/users")类级别映射基础路径。@RequestMapping("/users") public class UserController { ... }可省略,直接使用衍生注解。
@GetMapping@GetMapping("/{id}")处理 GET 请求,获取资源。@GetMapping("/{id}") public User findById(@PathVariable Long id) { ... }用于查询操作。
@PostMapping@PostMapping处理 POST 请求,创建资源。建议创建成功返回 201 Created 和 Location 头。返回 ResponseEntity.created(URI.create("/users/" + saved.getId())).body(saved)
@PutMapping@PutMapping("/{id}")处理 PUT 请求,更新整个资源。@PutMapping("/{id}") public User update(@PathVariable Long id, @RequestBody User user) { ... }应替换整个资源,客户端提供完整对象。
@DeleteMapping@DeleteMapping("/{id}")处理 DELETE 请求,删除资源。删除成功建议返回 204 No Content。使用 ResponseEntity.noContent().build()
@PatchMapping@PatchMapping("/{id}")处理 PATCH 请求,部分更新资源。@PatchMapping("/{id}") public User partialUpdate(@PathVariable Long id, @RequestBody Map<String, Object> updates) { ... }需手动处理字段更新逻辑。
ResponseEntityResponseEntity封装响应体、状态码、响应头,实现精细控制。见上文 POST 示例推荐用于需要自定义状态码的场景。

5.3 请求与响应数据格式(JSON/XML)

特性说明配置方式/代码示例注意事项
默认支持 JSONSpring Boot 默认使用 Jackson 实现 Java 对象与 JSON 的序列化/反序列化。引入 spring-boot-starter-web 即自动包含 Jackson。无需额外配置即可处理 JSON。
@RequestBody将请求体中的 JSON 自动反序列化为 Java 对象。@PostMapping("/users") public User create(@RequestBody User user) { ... }请求头需设置 Content-Type: application/json
@ResponseBody将返回对象自动序列化为 JSON 响应。方法返回对象即可,@RestController 已隐含。响应头自动设置 Content-Type: application/json
支持 XML添加 Jackson XML 依赖后可支持 XML 格式。依赖:com.fasterxml.jackson.dataformat:jackson-dataformat-xml;请求头 Accept: application/xml需 Java 类有默认构造函数和 getter/setter。
@JacksonXmlRootElement指定 XML 根元素名称。@JacksonXmlRootElement(localName = "user") public class User { ... }用于 XML 序列化。
内容协商(Content Negotiation)根据请求头 Accept 或参数决定返回 JSON 还是 XML。访问 /users?format=xml 或设置 Accept: application/xml可通过 spring.mvc.contentnegotiation.favor-parameter=true 启用参数模式。
Jackson 注解控制序列化使用 @JsonIgnore, @JsonProperty, @JsonFormat 等定制 JSON 输出。@JsonIgnore private String password;@JsonFormat(pattern = "yyyy-MM-dd") private LocalDate birthday;提高数据安全性和格式控制。

5.4 全局异常处理(@ControllerAdvice、@ExceptionHandler)

注解/方法语法用途代码示例注意事项
@ControllerAdvice@ControllerAdvice定义全局异常处理器,应用于所有控制器。@ControllerAdvice public class GlobalExceptionHandler { ... }可指定包范围:@ControllerAdvice(basePackages = "com.example.controller")
@ExceptionHandler@ExceptionHandler(ResourceNotFoundException.class)捕获指定类型的异常并返回统一响应。返回 ResponseEntity.status(HttpStatus.NOT_FOUND).body(error)可处理多种异常类型。
处理 Validation 异常@ExceptionHandler(MethodArgumentNotValidException.class)捕获参数校验失败异常。遍历 ex.getBindingResult().getFieldErrors() 收集错误信息需结合 @Valid 使用。
处理通用异常@ExceptionHandler(Exception.class)捕获未预期的异常,避免暴露堆栈信息。返回 500 内部错误,记录日志应放在最后,避免屏蔽特定异常处理。
自定义异常类public class ResourceNotFoundException extends RuntimeException定义业务异常,便于识别和处理。public class ResourceNotFoundException extends RuntimeException { public ResourceNotFoundException(String message) { super(message); } }继承 RuntimeException 可避免强制捕获。
返回结构统一定义 ErrorResponse 类封装错误信息。public class ErrorResponse { private String code; private String message; }提高 API 可用性和前端处理一致性。

5.5 API 文档生成(Springdoc OpenAPI / Swagger)

组件/注解语法用途代码示例注意事项
springdoc-openapi 依赖Maven: org.springdoc:springdoc-openapi-starter-webmvc-ui集成 OpenAPI 3 和 Swagger UI。Spring Boot 3 推荐使用 starter-webmvc-ui替代已停更的 springfox-swagger
访问 Swagger UI启动后访问 http://localhost:8080/swagger-ui.html图形化 API 文档界面,支持在线测试。路径可配置:springdoc.swagger-ui.path=/api-docs生产环境建议禁用或加权限。
@Operation@Operation(summary = "获取用户详情", description = "根据ID查询用户信息")描述接口方法的用途。用于 @GetMapping 等方法上提升文档可读性。
@Parameter@Parameter(description = "用户ID", required = true)描述参数信息。用于 @PathVariable@RequestParam 等参数前可用于路径、查询参数等。
@Schema@Schema(description = "用户实体")描述数据模型。@Schema(description = "用户信息") public class User { @Schema(description = "用户唯一ID", example = "1") private Long id; }用于 POJO 类或字段。
@ApiResponse@ApiResponse(responseCode = "200", description = "成功获取用户")描述响应状态码和含义。用于 @Operationresponses 属性明确接口契约。
分组配置@Tag(name = "用户管理")将接口分组显示。@Tag(name = "用户管理", description = "用户增删改查接口") public class UserController { ... }在 Swagger UI 中按组展示。
安全方案@SecurityScheme定义认证方式(如 JWT)。@SecurityScheme(name = "bearerAuth", type = SecuritySchemeType.HTTP, scheme = "bearer", bearerFormat = "JWT")配合 @SecurityRequirement 使用。

第六章:依赖注入与 Bean 管理

6.1 IoC 容器与依赖注入(DI)原理

概念说明注意事项
IoC(Inversion of Control,控制反转)将对象的创建和管理权从程序代码中转移到外部容器(Spring 容器),实现解耦。传统方式由 new 创建对象,IoC 由容器注入,降低耦合度。
DI(Dependency Injection,依赖注入)IoC 的实现方式之一,容器在运行时将依赖对象”注入”到目标对象中。常见注入方式:构造器注入、Setter 注入、字段注入。
Spring IoC 容器核心是 ApplicationContext 接口,负责 Bean 的生命周期管理、配置、依赖解析。常用实现类:AnnotationConfigApplicationContext(Java 配置)、ClassPathXmlApplicationContext(XML 配置)。
Bean由 Spring IoC 容器管理的 Java 对象,也称为 Spring 组件。所有被 @Component@Service 等注解标记的类实例都是 Bean。
配置元数据容器如何创建和装配 Bean 的信息来源,可以是注解、Java 配置类或 XML 文件。Spring Boot 推荐使用注解和 Java 配置。
依赖查找 vs 依赖注入依赖查找是主动从容器获取 Bean(如 context.getBean()),依赖注入是被动接收。推荐使用依赖注入,更符合 IoC 理念。

6.2 Bean 的定义与注册(@Component、@Service、@Repository、@Controller)

注解语法用途代码示例注意事项
@Component@Component通用注解,标识一个类为 Spring 管理的组件,可被自动扫描并注册为 Bean。@Component public class EmailService { ... }是其他特定注解的元注解。
@Service@Service用于业务逻辑层(Service 层)的类,语义更明确。@Service public class UserService { @Autowired private UserRepository userRepository; }@Component 功能相同,但层次清晰。
@Repository@Repository用于数据访问层(DAO/Repository 层),能自动捕获持久层异常并转换为 Spring 的 DataAccessException@Repository public class UserRepository { ... }推荐用于数据访问类。
@Controller@Controller用于表现层(Web 层),结合 Spring MVC 处理 HTTP 请求。@Controller public class UserController { ... }通常返回视图名。
@RestController@RestController用于 RESTful Web 服务,等价于 @Controller + @ResponseBody@RestController public class ApiUserController { ... }返回数据(如 JSON),不返回视图。
@ComponentScan@ComponentScan(basePackages = "com.example")启用组件扫描,自动发现并注册标注了上述注解的类为 Bean。@SpringBootApplication 已包含此注解,默认扫描启动类所在包及其子包。无需手动配置,除非包结构特殊。

6.3 @Autowired 与 @Qualifier 注解详解

注解/方式语法用途代码示例注意事项
@Autowired@Autowired自动装配 Bean,可标注在字段、构造器、Setter 方法或参数上。@Service public class UserService { @Autowired private UserRepository userRepository; }默认按类型(byType)匹配。
构造器注入@Autowired 构造器推荐方式,确保依赖不可变且不为 null。@Autowired public UserService(UserRepository userRepository) { this.userRepository = userRepository; }Spring 4.3+ 若类只有一个构造器,@Autowired 可省略。
Setter 注入@Autowired setter 方法用于可选依赖或需要运行时更改依赖的场景。@Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; }依赖可变,不推荐作为主要方式。
字段注入@Autowired 字段直接在字段上使用,代码简洁但不利于测试和不可变性。@Autowired private EmailService emailService;不推荐,违反封装原则。
@Qualifier@Qualifier("specificBean")当存在多个同类型 Bean 时,指定具体 Bean 的名称。@Autowired @Qualifier("emailService") private MessageService service;必须与 @Autowired 配合使用。
required = false@Autowired(required = false)指定依赖为可选,若找不到 Bean 不报错。@Autowired(required = false) private OptionalService optionalService;若未找到,字段为 null,需判空处理。

6.4 Bean 的作用域(@Scope)

作用域语法用途代码示例注意事项
singleton@Scope("singleton") 或默认每个 Spring IoC 容器中仅存在一个 Bean 实例,为默认作用域。@Service @Scope("singleton") public class UserService { ... }多数 Bean 使用此作用域。
prototype@Scope("prototype")每次请求 Bean 时都创建一个新实例。@Component @Scope("prototype") public class RequestTracker { ... }适合有状态的 Bean。
request@Scope("request")每个 HTTP 请求创建一个实例,仅在 Web 环境有效。@Component @Scope("request") public class UserSessionData { ... }实例生命周期与请求一致。
session@Scope("session")每个 HTTP 会话创建一个实例,仅在 Web 环境有效。@Component @Scope("session") public class UserPreferences { ... }适合存储用户会话数据。
application@Scope("application")每个 ServletContext 生命周期内创建一个实例,仅在 Web 环境有效。@Component @Scope("application") public class AppSettings { ... }类似于 singleton,但绑定到 ServletContext
websocket@Scope("websocket")每个 WebSocket 会话创建一个实例,仅在 WebSocket 环境有效。@Component @Scope("websocket") public class WebSocketSessionData { ... }较少使用。
自定义作用域实现 Scope 接口并注册满足特殊生命周期需求。需通过 ConfigurableBeanFactory.registerScope() 注册。高级用法,一般无需自定义。

6.5 Bean 的生命周期回调(@PostConstruct、@PreDestroy)

方法/注解语法用途代码示例注意事项
@PostConstruct@PostConstruct标注在方法上,Bean 初始化完成后执行,用于执行初始化逻辑。@Component public class DatabaseInitializer { @PostConstruct public void init() { System.out.println("数据库连接初始化..."); } }方法必须为 public void,无参数,不能是静态。
@PreDestroy@PreDestroy标注在方法上,Bean 销毁前执行,用于释放资源。@Component public class ConnectionPool { @PreDestroy public void cleanup() { System.out.println("关闭数据库连接池..."); } }仅在 singleton Bean 且容器正常关闭时调用。
InitializingBean 接口implements InitializingBean实现 afterPropertiesSet() 方法,替代 @PostConstructpublic class MyBean implements InitializingBean { @Override public void afterPropertiesSet() { ... } }不推荐,与 Spring API 耦合。
DisposableBean 接口implements DisposableBean实现 destroy() 方法,替代 @PreDestroypublic class MyBean implements DisposableBean { @Override public void destroy() { ... } }不推荐,与 Spring API 耦合。
自定义初始化方法@Bean(initMethod = "init")@Bean 注解中指定初始化方法。@Bean(initMethod = "start") public MyService myService() { return new MyService(); }适用于第三方类无法加注解时。
自定义销毁方法@Bean(destroyMethod = "shutdown")@Bean 注解中指定销毁方法。@Bean(destroyMethod = "shutdown") public DataSource dataSource() { ... }同上。
执行顺序构造器 → 依赖注入 → @PostConstruct / InitializingBean → 使用 → @PreDestroy / DisposableBeanBean 生命周期各阶段执行顺序。确保资源在使用前初始化,销毁前释放。@PostConstruct 在依赖注入完成后执行。

第七章:AOP 与切面编程

7.1 AOP 核心概念(切面、连接点、通知、切入点)

概念说明示例
AOP(Aspect-Oriented Programming)面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护,用于解耦横切关注点(如日志、事务)。将日志记录从业务代码中分离。
切面(Aspect)横切关注点的模块化,通常是一个类,包含多个通知和切入点。LoggingAspect 类用于统一处理日志。
连接点(Join Point)程序执行过程中能够插入切面的点,如方法调用、异常抛出等。在 Spring AOP 中,仅支持方法执行连接点。任意 public 方法的调用。
通知(Advice)切面在特定连接点上执行的动作(代码逻辑)。在方法执行前打印日志。
切入点(Pointcut)匹配连接点的表达式,定义在哪些连接点上应用通知。execution(* com.example.service.*.*(..))
目标对象(Target Object)被一个或多个切面所通知的对象(即被代理的对象)。UserService 实例。
代理(Proxy)AOP 框架创建的对象,用于实现切面契约(如 JDK 动态代理或 CGLIB 代理)。Spring 自动创建代理对象。
织入(Weaving)将切面应用到目标对象并创建代理对象的过程。编译时、类加载时或运行时织入(Spring 使用运行时织入)。

7.2 使用 @Aspect 定义切面

步骤/注解说明代码示例注意事项
添加依赖引入 spring-boot-starter-aopMaven: org.springframework.boot:spring-boot-starter-aopSpring Boot 项目只需添加此依赖即可启用 AOP。
启用 AOP使用 @EnableAspectJAutoProxy(Spring Boot 已自动配置)无需手动添加,@SpringBootApplication 已包含。一般无需显式声明。
定义切面类使用 @Aspect@Component 标注类@Aspect @Component public class LoggingAspect { ... }必须被 Spring 容器管理(如加 @Component)。
切面优先级使用 @Order 注解控制多个切面的执行顺序@Aspect @Component @Order(1) public class SecurityAspect { ... }数值越小,优先级越高。

7.3 通知类型详解(@Before、@After、@Around、@AfterReturning、@AfterThrowing)

通知类型语法用途代码示例执行时机
@Before@Before("pointcut()")在目标方法执行前执行。@Before("execution(* com.example.service.*.*(..))") public void logBefore(JoinPoint jp) { System.out.println("方法执行前: " + jp.getSignature()); }方法调用前
@After@After("pointcut()")在目标方法执行后执行(无论是否抛出异常),类似 finally。@After("pointcut()") public void logAfter(JoinPoint jp) { System.out.println("方法执行后: " + jp.getSignature()); }方法执行后(正常或异常)
@AfterReturning@AfterReturning(pointcut = "pointcut()", returning = "result")在目标方法成功执行并返回后执行,可获取返回值。@AfterReturning(pointcut = "pointcut()", returning = "result") public void logReturn(JoinPoint jp, Object result) { System.out.println("返回值: " + result); }方法正常返回后
@AfterThrowing@AfterThrowing(pointcut = "pointcut()", throwing = "ex")在目标方法抛出异常后执行,可捕获异常。@AfterThrowing(pointcut = "pointcut()", throwing = "ex") public void logException(JoinPoint jp, Exception ex) { System.out.println("异常: " + ex.getMessage()); }方法抛出异常后
@Around@Around("pointcut()")环绕通知,最强大的通知类型,可自定义目标方法执行前后逻辑,甚至决定是否执行目标方法。@Around("pointcut()") public Object measureTime(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); Object result = pjp.proceed(); long duration = System.currentTimeMillis() - start; System.out.println("耗时: " + duration + "ms"); return result; }包裹整个方法执行过程

7.4 切入点表达式语法

表达式类型语法示例说明
execution()execution(* com.example.service.*.*(..))匹配方法执行,最常用。* 表示任意返回类型,.. 表示任意参数。
within()within(com.example.service.*)匹配指定类型内的方法执行。
this()this(com.example.service.UserService)匹配代理对象类型为指定类型的 bean。
target()target(com.example.service.UserService)匹配目标对象类型为指定类型的 bean。
args()args(java.lang.String, ..)匹配参数列表,第一个参数为 String 类型。
@target()@target(org.springframework.stereotype.Service)匹配带有指定注解的类。
@args()@args(com.example.annotation.Loggable)匹配传入参数带有指定注解的方法。
@within()@within(org.springframework.stereotype.Service)匹配带有指定注解的类中的所有方法。
@annotation()@annotation(com.example.annotation.LogExecution)匹配被指定注解标注的方法。
组合表达式@annotation(LogExecution) && args(name, ..)使用 &&、`

7.5 AOP 实际应用场景(日志、权限、事务等)

应用场景实现方式说明
日志记录使用 @Before@AfterReturning 记录方法调用、参数、返回值、耗时。统一记录业务操作日志,便于排查问题。
性能监控使用 @Around 记录方法执行时间。识别系统性能瓶颈。
权限校验使用 @Before 拦截方法,检查用户权限。在进入敏感方法前进行安全控制。
事务管理Spring 内置 @Transactional 使用 AOP 实现。声明式事务,无需手动管理提交/回滚。
缓存管理Spring Cache 抽象基于 AOP,使用 @Cacheable 等注解。自动缓存方法结果,提高性能。
参数校验在方法执行前使用 AOP 检查参数合法性。可结合 JSR-303 注解实现。
分布式追踪在方法调用前后注入 Trace ID,实现链路追踪。如集成 Sleuth、SkyWalking。

第八章:Spring Boot 高级特性

8.1 条件化配置(@Conditional 注解族)

注解用途示例
@ConditionalOnClass存在指定类时才创建 Bean。@Bean @ConditionalOnClass(DataSource.class) public MyDataSourceConfig config() { ... }
@ConditionalOnMissingClass不存在指定类时才创建 Bean。用于兼容不同环境。
@ConditionalOnBean存在指定 Bean 时才创建当前 Bean。@Bean @ConditionalOnBean(name = "dataSource") public JdbcTemplate jdbcTemplate(DataSource ds) { ... }
@ConditionalOnMissingBean不存在指定 Bean 时才创建当前 Bean(防止重复定义)。常用于 Starter 中提供默认实现。
@ConditionalOnProperty指定配置属性存在且值为 true 时生效。@Bean @ConditionalOnProperty(name = "feature.enabled", havingValue = "true") public FeatureService featureService() { ... }
@ConditionalOnWebApplication当前为 Web 应用时生效。区分 Web 和非 Web 环境。
@ConditionalOnNotWebApplication当前不是 Web 应用时生效。
@Conditional自定义条件,实现 Condition 接口。public class MyCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { return "prod".equals(context.getEnvironment().getProperty("spring.profiles.active")); } }

8.2 自定义 Starter 的开发

步骤说明示例
命名规范官方 Starter:spring-boot-starter-xxx;第三方:xxx-spring-boot-startermyfeature-spring-boot-starter
创建 autoconfigure 模块包含自动配置类、条件化 Bean、配置属性类。MyFeatureAutoConfiguration
创建 starter 模块仅依赖 autoconfigure 模块,简化引入。myfeature-spring-boot-starter
自动配置类使用 @Configuration + @Conditional 系列注解。@Configuration @ConditionalOnClass(MyService.class) public class MyFeatureAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService() { return new MyService(); } }
配置属性使用 @ConfigurationProperties 绑定 application.yml 中的配置。@ConfigurationProperties("myfeature") public class MyFeatureProperties { private String host; private int port; // getter/setter }
spring.factoriesresources/META-INF/spring.factories 中注册自动配置类。org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.example.MyFeatureAutoConfiguration
测试在 demo 项目中引入 starter,验证自动配置是否生效。compileOnly 'org.springframework.boot:spring-boot-autoconfigure-processor'

8.3 事件驱动模型(ApplicationEvent 与 ApplicationListener)

组件说明示例
ApplicationEvent事件载体,继承此类定义自定义事件。public class UserRegisteredEvent extends ApplicationEvent { private final User user; public UserRegisteredEvent(User user) { super(user); this.user = user; } public User getUser() { return user; } }
ApplicationListener监听特定事件,实现 onApplicationEvent() 方法。@Component public class UserEventListener implements ApplicationListener<UserRegisteredEvent> { @Override public void onApplicationEvent(UserRegisteredEvent event) { System.out.println("用户注册: " + event.getUser().getName()); } }
@EventListener更简洁的监听方式,无需实现接口。@Component public class UserService { @EventListener public void handleUserRegistration(UserRegisteredEvent event) { sendWelcomeEmail(event.getUser()); } }
发布事件使用 ApplicationEventPublisher 发布事件。@Service public class UserService { @Autowired private ApplicationEventPublisher publisher; public void register(User user) { publisher.publishEvent(new UserRegisteredEvent(user)); } }
异步监听使用 @Async 实现事件异步处理。@EventListener @Async public void handleAsync(UserRegisteredEvent event) { ... } 需启用 @EnableAsync

8.4 国际化(i18n)支持

配置/组件说明示例
消息文件messages_{locale}.properties 命名,如 messages_en.propertiesmessages_zh_CN.propertiesmessages_zh_CN.propertieswelcome=欢迎, {0}
MessageSourceSpring 提供的消息解析接口,通常使用 ResourceBundleMessageSource@Bean public MessageSource messageSource() { ResourceBundleMessageSource source = new ResourceBundleMessageSource(); source.setBasename("messages"); source.setDefaultEncoding("UTF-8"); return source; }
LocaleResolver决定当前请求的 Locale,如 AcceptHeaderLocaleResolver(默认)、CookieLocaleResolver@Bean public LocaleResolver localeResolver() { CookieLocaleResolver resolver = new CookieLocaleResolver(); resolver.setDefaultLocale(Locale.SIMPLIFIED_CHINESE); return resolver; }
切换语言通过 LocaleChangeInterceptor 监听参数(如 ?lang=en)切换语言。注册 LocaleChangeInterceptor 并设置 paramName"lang",在 addInterceptors 中注册。
使用消息在代码或 Thymeleaf 中使用 #messages 获取国际化文本。Java: messageSource.getMessage("welcome", new Object[]{"张三"}, locale);Thymeleaf: <p th:text="#{welcome(${user.name})}">Welcome</p>

8.5 缓存抽象(@Cacheable、@CacheEvict 等)

注解语法用途示例注意事项
@EnableCaching标注在配置类上,启用缓存支持。@SpringBootApplication 已包含此功能。必须启用才能使用缓存注解。
@Cacheable@Cacheable("users")标注在方法上,执行前检查缓存,命中则返回缓存值,否则执行方法并缓存结果。@Cacheable("users") public User findById(Long id) { return userRepository.findById(id); }key 默认为方法参数,可用 key 属性自定义。
@CachePut@CachePut("users", key = "#user.id")方法始终执行,并将结果存入缓存(用于更新)。@CachePut("users", key = "#user.id") public User update(User user) { ... }不检查缓存,直接执行并更新。
@CacheEvict@CacheEvict("users", key = "#id")清除指定缓存条目。@CacheEvict("users", key = "#id") public void delete(Long id) { ... }可设置 allEntries = true 清空整个缓存区。
@Caching@Caching(evict = { @CacheEvict("users"), @CacheEvict(value = "cache2", key = "#id") })组合多个缓存操作。用于复杂缓存逻辑。
缓存管理器ConcurrentMapCacheManager(内存)、RedisCacheManagerCaffeineCacheManager配置 spring.cache.type=redis 自动配置 Redis 缓存。需引入对应依赖。
SpEL 表达式在注解中使用 SpEL 定义 key、condition 等。@Cacheable(value = "users", key = "#id", condition = "#id > 0")condition 满足时才缓存。

第九章:安全控制

9.1 Spring Security 简介与核心概念

概念说明注意事项
Spring Security一个功能强大且高度可定制的身份验证和访问控制框架,用于保护基于 Spring 的应用程序。是 Spring 生态中最主流的安全框架。
认证(Authentication)验证用户身份的过程,即”你是谁”。常见方式:用户名/密码、OAuth2、JWT。
授权(Authorization)在认证通过后,判断用户是否有权限执行某个操作,即”你能做什么”。基于角色(Role)或权限(Authority)控制。
SecurityContextHolder存储当前安全上下文(包含认证信息)的容器,可通过 SecurityContextHolder.getContext().getAuthentication() 获取当前用户。默认使用 ThreadLocal 存储,确保线程隔离。
Authentication 对象表示当前用户的认证信息,包含 principal(主体)、credentials(凭证)、authorities(权限)、authenticated(是否已认证)等。登录成功后由 AuthenticationManager 创建并存入上下文。
UserDetails载体接口,用于加载用户详细信息(如用户名、密码、权限、是否过期等)。需自定义实现类(如 CustomUserDetails)并由 UserDetailsService 返回。
UserDetailsService接口,用于根据用户名加载 UserDetails 对象。通常自定义实现,从数据库或其它存储中查询用户信息。
PasswordEncoder用于密码的加密与验证,防止明文存储。推荐使用 BCryptPasswordEncoder
Filter ChainSpring Security 通过一系列过滤器(Filter)实现安全控制,如 UsernamePasswordAuthenticationFilterFilterSecurityInterceptor 等。请求在到达控制器前需经过多个安全过滤器。

9.2 用户认证(Authentication)配置

配置项说明代码示例注意事项
添加依赖引入 spring-boot-starter-security<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>启用后所有接口默认受保护。
安全配置类使用新式配置(推荐 SecurityFilterChain Bean)。@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.authorizeHttpRequests(auth -> auth.requestMatchers("/public/**").permitAll().anyRequest().authenticated()).formLogin(); return http.build(); } }新版本推荐使用 SecurityFilterChain Bean。
自定义 UserDetailsService实现 UserDetailsService 接口,从数据库加载用户。@Service public class CustomUserDetailsService implements UserDetailsService { @Autowired private UserRepository userRepository; @Override public UserDetails loadUserByUsername(String username) { User user = userRepository.findByUsername(username) .orElseThrow(() -> new UsernameNotFoundException("User not found")); return org.springframework.security.core.userdetails.User .withUsername(user.getUsername()).password(user.getPassword()).authorities("ROLE_USER").build(); } }必须返回 UserDetails 实现类。
配置 PasswordEncoder定义密码编码器 Bean。@Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); }密码入库前需加密,登录时自动验证。
登录页面配置自定义登录页路径、登录处理 URL、成功/失败跳转。.formLogin(login -> login.loginPage("/login").loginProcessingUrl("/doLogin").defaultSuccessUrl("/home").failureUrl("/login?error").permitAll())loginProcessingUrl 是表单提交的 action。
注销配置配置注销 URL、成功跳转页。.logout(logout -> logout.logoutUrl("/logout").logoutSuccessUrl("/login").permitAll())默认 /logout,POST 请求。

9.3 授权(Authorization)与权限控制

配置项说明代码示例注意事项
基于 URL 的授权使用 authorizeHttpRequests() 配置不同路径的访问权限。.authorizeHttpRequests(auth -> auth.requestMatchers("/admin/**").hasRole("ADMIN").requestMatchers("/user/**").hasAnyRole("USER", "ADMIN").requestMatchers(HttpMethod.POST, "/api/**").hasAuthority("WRITE").anyRequest().authenticated())规则按顺序匹配,越精确的路径应越靠前。
角色与权限角色以 ROLE_ 开头(如 ROLE_ADMIN),权限可自定义(如 USER_READ)。hasRole("ADMIN") 等价于 hasAuthority("ROLE_ADMIN")
匿名访问使用 permitAll() 允许未认证用户访问。.requestMatchers("/public/**", "/login").permitAll()登录页、静态资源通常需放行。
拒绝访问使用 denyAll() 拒绝所有用户。.requestMatchers("/private/**").denyAll()用于临时关闭某些接口。
IP 限制限制特定 IP 或 IP 段访问。.requestMatchers("/admin/**").hasIpAddress("192.168.1.0/24")需在 HttpServletRequest 中获取真实 IP(考虑代理)。

9.4 方法级安全(@PreAuthorize、@Secured)

注解说明代码示例注意事项
@EnableMethodSecurity启用方法级安全注解(Spring Security 5.6+ 推荐)。@Configuration @EnableMethodSecurity public class MethodSecurityConfig { }替代旧的 @EnableGlobalMethodSecurity
@PreAuthorize在方法执行前进行权限检查,支持 SpEL 表达式。@PreAuthorize("hasRole('ADMIN')") public void deleteUser(Long id) { ... }@PreAuthorize("#userId == authentication.principal.id") public User getUser(Long userId) { ... }可访问方法参数和认证信息。
@PostAuthorize在方法执行后进行权限检查(较少使用)。@PostAuthorize("returnObject.owner == authentication.principal.username") public Document getDocument() { ... }方法已执行,仅用于结果校验。
@Secured基于角色的访问控制,不支持 SpEL。@Secured("ROLE_ADMIN") public void adminOnly() { ... }@Secured({"ROLE_USER", "ROLE_ADMIN"}) public void userOrAdmin() { ... }语法简单,但功能有限。
@RolesAllowedJSR-250 标准注解,类似 @Secured@RolesAllowed("ADMIN") public void criticalOperation() { ... }需启用 @EnableGlobalMethodSecurity(jsr250Enabled = true)

9.5 JWT 集成与无状态认证

组件/步骤说明代码示例/配置注意事项
JWT(JSON Web Token)一种无状态的令牌格式,包含 Header、Payload、Signature。用于前后端分离、微服务架构中的身份认证。令牌自包含,服务端无需存储会话。
添加 JWT 依赖io.jsonwebtoken:jjwt-api, jjwt-impl, jjwt-jackson<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-api</artifactId><version>0.11.5</version></dependency>注意版本兼容性。
JWT 工具类创建和解析 JWT 令牌。Jwts.builder().setSubject(username).setIssuedAt(new Date()).setExpiration(...).signWith(SignatureAlgorithm.HS512, SECRET_KEY).compact()秘钥需安全存储。
自定义过滤器继承 OncePerRequestFilter,在每次请求时检查 JWT。提取 token → 验证 → 设置 SecurityContextHolder.getContext().setAuthentication(auth)需注册到 SecurityFilterChain 中。
登录接口验证用户名密码后返回 JWT。@PostMapping("/login") public ResponseEntity<JwtResponse> login(@RequestBody LoginRequest request) { ... }不使用 Spring Security 默认登录流程。
放行登录接口SecurityFilterChain 中放行 /login.requestMatchers("/login", "/register").permitAll()避免登录接口被拦截。

第十章:测试

10.1 单元测试(JUnit 5 与 Mockito)

组件/注解说明代码示例注意事项
JUnit 5新一代 Java 测试框架,由 junit-platformjunit-jupiterjunit-vintage 组成。@Test void shouldReturnCorrectValue() { Calculator calc = new Calculator(); assertEquals(4, calc.add(2, 2)); }Spring Boot 2.2+ 默认使用 JUnit 5。
@Test标记测试方法。@Test void myTest() { ... }方法必须为 public void,可省略 public(JUnit 5 允许)。
断言(Assertions)assertEquals, assertTrue, assertNull, assertThrows 等。assertThrows(IllegalArgumentException.class, () -> service.process(null));提供丰富的断言方法。
Mockito模拟框架,用于创建 Mock 对象,模拟依赖行为。UserRepository mockRepo = mock(UserRepository.class); when(mockRepo.findById(1L)).thenReturn(Optional.of(new User("John")));隔离被测类与外部依赖。
@Mock创建 Mock 对象(需配合 @ExtendWith(MockitoExtension.class))。@ExtendWith(MockitoExtension.class) class UserServiceTest { @Mock private UserRepository userRepository; @InjectMocks private UserService userService; }自动注入 Mock 依赖。
@InjectMocks@Mock 对象注入到被测类中。见上例。适用于构造器或字段注入。

10.2 集成测试(@SpringBootTest)

注解/配置说明代码示例注意事项
@SpringBootTest启动完整的 Spring 应用上下文,用于测试组件间的集成。@SpringBootTest @TestPropertySource(locations = "classpath:application-test.properties") class UserServiceIntegrationTest { @Autowired private UserService userService; @Test void shouldSaveUser() { User saved = userService.save(new User("Alice")); assertNotNull(saved.getId()); } }加载 application.yml 配置,启动嵌入式容器(可选)。
webEnvironment指定 Web 环境模式。@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)RANDOM_PORTMOCK 使用 MockMvc,RANDOM_PORT 启动真实服务器。
@TestPropertySource指定测试专用的配置文件。@TestPropertySource(properties = "app.feature.enabled=false")避免影响生产配置。
@DirtiesContext标记测试类或方法后重置应用上下文。@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)用于状态被修改的测试,确保隔离。
TestRestTemplate用于发送 HTTP 请求测试 REST API(MOCK 模式)。@Autowired private TestRestTemplate restTemplate; @Test void shouldReturnUser() { ResponseEntity<User> response = restTemplate.getForEntity("/users/1", User.class); assertEquals(HttpStatus.OK, response.getStatusCode()); }RANDOM_PORT 模式下使用。

10.3 Web 层测试(@WebMvcTest)

注解/组件说明代码示例注意事项
@WebMvcTest仅加载 Web 层组件(如 @Controller@RestController),不加载其他 Bean。@WebMvcTest(UserController.class) class UserControllerTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; }用于快速测试控制器逻辑。
MockMvc模拟 MVC 请求,无需启动服务器。@Test void shouldReturnUser() throws Exception { when(userService.findById(1L)).thenReturn(new User("John")); mockMvc.perform(get("/users/1")).andExpect(status().isOk()).andExpect(jsonPath("$.name").value("John")); }支持链式调用,验证状态、JSON 内容等。
@MockBean为 Spring 上下文中的 Bean 创建 Mock 实例。@MockBean private UserService userService;替换容器中的真实 Bean。
ResultMatcher用于验证响应结果。status().isOk(), content().json(...), jsonPath("$.name").value("John")需引入 spring-boot-starter-test

10.4 数据层测试(@DataJpaTest)

注解/组件语法用途代码示例注意事项
@DataJpaTest@DataJpaTest专用于测试 JPA 数据访问层,加载最小化 Spring 上下文,默认启用内存数据库和事务管理。@DataJpaTest class UserRepositoryTest { @Autowired private TestEntityManager entityManager; @Autowired private UserRepository userRepository; @Test void findByEmail_shouldReturnUser() { User user = new User("john", "john@example.com"); entityManager.persistAndFlush(user); Optional<User> found = userRepository.findByEmail("john@example.com"); assertThat(found).isPresent(); assertThat(found.get().getName()).isEqualTo("john"); } }默认使用内存数据库(H2),仅加载 JPA 相关组件,每个测试方法在事务中自动回滚。
TestEntityManager@Autowired private TestEntityManager entityManager;Spring Boot 提供的工具类,用于在测试中持久化实体、刷新会话、清除缓存等。entityManager.persistAndFlush(user);推荐用于测试中插入测试数据。
@Rollback@Rollback(false)控制测试方法结束后是否回滚事务。默认为 true(回滚)。设置为 false 可保留数据(用于调试)。生产环境慎用。
@Sql@Sql("/test-data.sql")在测试方法执行前或后执行指定的 SQL 脚本。@Test @Sql("/user-test-data.sql") void whenUserExists_thenFindByEmail() { ... }支持 executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD
自定义数据源配置 application-test.properties 中的数据库连接属性。spring.datasource.url=jdbc:postgresql://localhost:5432/testdb需通过 @ActiveProfiles("test") 激活。

10.5 测试配置与 Mock 数据

技术/注解语法用途代码示例注意事项
@TestConfiguration@TestConfiguration在测试中定义额外的 Bean 或覆盖主配置中的 Bean。@TestConfiguration public class TestConfig { @Bean @Primary public EmailService mockEmailService() { return Mockito.mock(EmailService.class); } }使用 @Primary 确保测试 Bean 优先。
@MockBean@MockBean private EmailService emailService;为 Spring 上下文中的 Bean 创建 Mockito 模拟对象并替换原 Bean。@MockBean private UserRepository userRepository; @Test void getUser_shouldReturnFromMock() { when(userRepository.findById(1L)).thenReturn(Optional.of(new User("John"))); }适用于集成测试中隔离外部依赖。
@SpyBean@SpyBean private UserService userService;对真实 Bean 创建”间谍”对象,可部分模拟其方法。@SpyBean private EmailService emailService; @Test void sendEmail_shouldCallRealMethod() { doNothing().when(emailService).send(any()); }适用于需要保留大部分真实行为的场景。
@ActiveProfiles@ActiveProfiles("test")激活指定的 Spring Profile。@SpringBootTest @ActiveProfiles("test") class UserServiceTest { ... }用于区分开发、测试、生产环境的配置。
Mockito 模拟行为when(...).thenReturn(...) / doThrow(...).when(...)定义模拟对象的方法返回值或抛出异常。when(userRepository.findById(999L)).thenThrow(new EntityNotFoundException());灵活控制测试场景。
@DirtiesContext@DirtiesContext标记测试类或方法会”污染”应用上下文,测试后需重建。@Test @DirtiesContext void changeGlobalState_shouldRebuildContext() { ... }影响性能,仅在必要时使用。
嵌入式数据库使用 H2、HSQLDB 等内存数据库用于快速、隔离的数据层测试。spring.datasource.url=jdbc:h2:mem:testdb推荐用于单元测试和集成测试。

第十一章:部署与监控

11.1 打包方式(Jar 与 War)

打包方式说明适用场景配置方式注意事项
可执行 JAR(Executable JAR)Spring Boot 默认打包方式,内置 Tomcat/Jetty/Undertow 容器,通过 java -jar app.jar 启动。微服务、独立应用、云原生部署。pom.xml<packaging>jar</packaging>(默认)。启动简单,无需外部容器;包含所有依赖,文件较大;支持 fat jar 结构。
WAR 包传统 Web 应用打包格式,需部署到外部 Servlet 容器(如 Tomcat)。企业传统环境、需共享容器资源、与旧系统共存。<packaging>war</packaging>,主类继承 SpringBootServletInitializer,重写 configure 方法。需外部容器支持;可与其他 WAR 共享容器;启动速度略慢于 JAR。
Thin JAR使用 spring-boot-thin-layout 插件,仅打包项目代码,依赖在运行时下载。CI/CD 流水线、节省存储空间、快速部署。添加 spring-boot-thin-layout 插件。首次启动需联网下载依赖;适合网络稳定的环境。

11.2 使用 Maven/Gradle 构建项目

工具说明构建命令配置文件优势
Maven基于 XML 的构建工具,结构标准化,插件生态丰富。mvn clean / mvn compile / mvn test / mvn package / mvn install / mvn spring-boot:runpom.xml标准化强,Spring Initializr 默认支持,适合大型企业项目。
Gradle基于 Groovy/Kotlin DSL 的构建工具,性能更高,配置更灵活。gradle build / gradle bootRun / gradle testbuild.gradlebuild.gradle.kts构建速度快(增量编译),脚本化配置,Android 开发标准工具。
Spring Boot 插件提供打包、运行、依赖管理等功能。Maven: spring-boot-maven-plugin;Gradle: id 'org.springframework.boot' version '3.3.3'pom.xml / build.gradle自动打包为可执行 JAR/WAR,内置依赖版本管理。

11.3 部署到服务器(Tomcat、Docker)

部署方式步骤说明注意事项
部署到外部 Tomcat1. 打包为 WAR;2. 复制到 tomcat/webapps/;3. 启动 Tomcat:bin/startup.sh适用于传统 Java EE 环境。确保 Tomcat 版本兼容;检查端口冲突(默认 8080);日志位于 logs/catalina.out
Docker 部署(推荐)编写 Dockerfile → docker build -t myapp:1.0 .docker run -d -p 8080:8080 myapp:1.0实现环境一致性、快速部署、弹性伸缩。使用 .dockerignore 忽略不必要文件;推荐使用多阶段构建优化镜像大小。
云平台部署如 AWS ECS、阿里云容器服务、Kubernetes结合 CI/CD 实现自动化部署。配置健康检查;设置资源限制(CPU、内存);使用 Secret 管理敏感配置。

11.4 Actuator 监控端点使用

端点默认路径是否敏感用途启用配置
/health/actuator/health否(生产建议保护)显示应用健康状态(数据库、磁盘、自定义检查)。management.endpoints.web.exposure.include=health,info,metrics
/info/actuator/info显示应用信息(版本、构建时间等)。application.yml 中配置 info.app.nameinfo.app.version
/metrics/actuator/metrics展示 JVM、HTTP 请求、线程等指标。可查看具体指标如 /actuator/metrics/jvm.memory.used
/env/actuator/env显示所有环境变量和配置属性。建议生产环境禁用或保护。
/beans/actuator/beans显示所有 Spring Bean 及其依赖关系。调试依赖注入问题。
/conditions/actuator/conditions显示自动配置类的匹配/不匹配原因。排查自动配置问题。
/loggers/actuator/loggers动态调整日志级别。POST /actuator/loggers/com.example 设置 {"configuredLevel": "DEBUG"}
/shutdown/actuator/shutdown是(默认关闭)关闭应用(需启用)。management.endpoint.shutdown.enabled=true

安全提示:生产环境应通过 Spring Security 保护敏感端点,或仅在内网暴露。

11.5 自定义健康检查与指标暴露

功能实现方式代码示例说明
自定义健康检查实现 HealthIndicator 接口或使用 @Component 标注类。@Component public class DatabaseHealthIndicator implements HealthIndicator { @Autowired private DataSource dataSource; @Override public Health health() { try (Connection conn = dataSource.getConnection()) { if (conn.isValid(1)) { return Health.up().withDetail("database", "MySQL").build(); } } catch (SQLException e) { return Health.down(e).build(); } return Health.down().build(); } }访问 /actuator/health 将包含自定义检查结果。
自定义指标(Metrics)使用 MeterRegistry 注册计数器、计时器等。@Service public class UserService { @Autowired private MeterRegistry meterRegistry; public User createUser(User user) { meterRegistry.counter("user.create.count").increment(); return Timer.builder("user.create.duration").register(meterRegistry).record(() -> userRepository.save(user)); } }指标可通过 /actuator/metrics 查看,也可集成 Prometheus。
Prometheus 集成添加 micrometer-registry-prometheus 依赖。访问 /actuator/prometheus 获取指标数据,供 Prometheus 抓取。用于构建监控告警系统(如 Grafana 展示)。

第十二章:微服务基础(可选扩展)

12.1 微服务架构概述

概念说明优势挑战
微服务架构将单体应用拆分为多个小型、独立部署的服务,每个服务围绕业务能力构建。- 技术异构性
- 独立部署
- 弹性伸缩
- 故障隔离
- 分布式复杂性
- 数据一致性
- 服务治理
- 运维成本高
服务拆分原则按业务边界(如用户、订单、支付)拆分,高内聚、低耦合。避免”分布式单体”。推荐使用领域驱动设计(DDD)指导拆分。
通信方式同步:HTTP/REST、gRPC
异步:消息队列(Kafka、RabbitMQ)
REST 简单通用,gRPC 高性能。注意超时、重试、熔断机制。
Spring CloudSpring 提供的微服务开发工具集,整合 Netflix、Alibaba 等组件。快速构建微服务生态系统。生态演进快,需关注版本兼容性。

12.2 使用 Spring Cloud Alibaba/Nacos 进行服务注册与发现

组件说明配置示例作用
Nacos Server阿里开源的注册中心与配置中心,支持服务发现、健康检查、动态配置。下载启动:sh bin/startup.sh -m standalone替代 Eureka + Config Server。
服务提供者向 Nacos 注册自身服务。yaml spring.cloud.nacos.discovery.server-addr: 127.0.0.1:8848
@SpringBootApplication @EnableDiscoveryClient public class UserServiceApplication { ... }
启动后在 Nacos 控制台可见。
服务消费者从 Nacos 发现服务并调用。同上配置 nacos.discovery.server-addr使用 RestTemplate + @LoadBalanced 或 OpenFeign 调用。
健康检查Nacos 自动检测服务实例健康状态,自动剔除故障节点。默认基于心跳机制。保障服务调用的可靠性。

12.3 OpenFeign 声明式服务调用

功能说明代码示例注意事项
声明式 HTTP 客户端通过接口 + 注解方式调用远程服务,无需手动拼接 URL。@FeignClient(name = "order-service", path = "/orders") public interface OrderClient { @GetMapping("/{id}") Order findById(@PathVariable("id") Long id); @PostMapping Order create(@RequestBody Order order); }- 必须启用 @EnableFeignClients
- 依赖服务名注册到注册中心
集成负载均衡自动集成 Ribbon 或 Spring Cloud LoadBalancer。调用 orderClient.findById(1L) 时自动选择实例。无需手动指定 IP 和端口。
超时与重试可配置连接、读取超时及重试策略。yaml feign.client.config.default.connectTimeout: 5000 feign.client.config.default.readTimeout: 5000避免雪崩效应。

12.4 Gateway 网关使用

功能说明配置示例作用
API 网关统一入口,负责路由、鉴权、限流、日志等横切关注点。使用 spring-cloud-starter-gateway隐藏内部服务结构。
路由配置定义请求路径到微服务的映射规则。yaml spring.cloud.gateway.routes: - id: user-service uri: lb://user-service predicates: - Path=/api/users/**lb:// 表示从注册中心负载均衡调用。
过滤器(Filter)在请求前后执行逻辑,如添加头、权限校验。自定义 GlobalFilter 或使用内置过滤器。实现统一认证、日志记录。
限流(Rate Limiting)基于 Redis 实现请求频率控制。使用 RequestRateLimiter 过滤器。防止恶意请求或系统过载。

12.5 分布式配置中心

组件说明配置方式优势
Nacos ConfigNacos 提供的动态配置管理功能。yaml spring.cloud.nacos.config.server-addr: 127.0.0.1:8848 spring.cloud.nacos.config.group: DEFAULT_GROUP spring.cloud.nacos.config.namespace: public spring.cloud.nacos.config.file-extension: yaml- 配置实时推送
- 多环境管理(dev/test/prod)
- 版本回滚
配置自动刷新使用 @RefreshScope 使 Bean 在配置更新后重新加载。@Component @RefreshScope public class FeatureToggle { @Value("${feature.enabled:false}") private boolean enabled; }无需重启服务即可生效。
配置优先级命令行 > JVM 参数 > bootstrap.yml > 远程配置中心 > 本地 application.yml合理设计配置层级。便于环境差异化配置。