Spring Boot 3.2.4 核心实战指南
基于 JDK21 LTS + Spring Boot 3.2.4,专注于核心痛点与解决方案
一、痛点分析:Spring Boot 开发中的常见问题
1.1 传统 Java 开发痛点
- 配置繁琐:XML 配置冗长,维护成本高
- 依赖管理复杂:手动管理依赖版本,容易冲突
- 部署困难:需要外部容器,部署流程复杂
- 开发效率低:重复代码多,开发周期长
- 性能瓶颈:线程模型限制,高并发场景性能不足
- 技术栈陈旧:依赖旧版本 JDK 和 Java EE,缺少现代特性
1.2 Spring Boot 3 面临的挑战
- Jakarta EE 迁移 :从
javax.*到jakarta.*的包名变更 - 虚拟线程适配:如何充分利用 JDK 21 虚拟线程
- AOT 编译与原生镜像:如何优化启动速度和内存占用
- 中间件集成:如何简化与各种中间件的集成
- 生产环境优化:如何实现高性能、高可用的生产部署
二、解决方案:Spring Boot 3 核心特性
2.1 自动配置与起步依赖
- 自动配置:基于条件判断的智能配置,减少手动配置
- 起步依赖:一键引入相关依赖,自动管理版本
- 约定大于配置:合理的默认配置,减少决策成本
2.2 性能优化
- 虚拟线程支持:原生集成 JDK 21 虚拟线程,提升高并发性能
- AOT 编译:提前编译,减少运行时开销
- GraalVM 原生镜像:启动速度提升 10 倍+,内存占用降低 50%+
- ZGC 垃圾收集器:默认启用,低延迟高吞吐量
2.3 现代化 API
- Jakarta EE 10 :全面使用
jakarta.*包名,告别javax.* - SpringDoc OpenAPI 3.0:默认集成,替代已停止维护的 Swagger 2
- JDK 21 特性:支持记录类、密封类、模式匹配等现代语法
2.4 简化开发体验
- DevTools:热重载,提高开发效率
- Actuator:内置监控,方便运维
- 统一异常处理:简化错误处理
- RESTful API 支持:内置 REST 功能,快速构建 API
三、核心原理:Spring Boot 3 底层机制
3.1 自动配置原理
3.1.1 实现机制
- @EnableAutoConfiguration:开启自动配置功能
- spring.factories:定义自动配置类
- @Conditional:条件化配置,根据环境决定是否启用配置
- @ConfigurationProperties:绑定配置属性
3.1.2 执行流程
- 应用启动时,Spring Boot 会扫描
META-INF/spring.factories文件 - 加载其中定义的自动配置类
- 根据
@Conditional注解的条件判断是否启用配置 - 将配置类中的 Bean 注册到 Spring 容器
3.1.3 源码分析
java
// Spring Boot 启动流程
public class SpringApplication {
public ConfigurableApplicationContext run(String... args) {
// 1. 准备环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 2. 创建应用上下文
ConfigurableApplicationContext context = createApplicationContext();
// 3. 准备上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 4. 刷新上下文
refreshContext(context);
// 5. 执行启动后的操作
afterRefresh(context, applicationArguments);
return context;
}
}
// 自动配置核心类
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({SqlSessionFactory.class, SqlSessionFactoryBean.class})
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration {
// 自动配置逻辑
}
3.2 虚拟线程原理
3.2.1 实现机制
- Continuation:虚拟线程的底层实现,支持挂起和恢复
- 调度器:JVM 内置的虚拟线程调度器,负责虚拟线程的调度
- 载体线程:执行虚拟线程代码的平台线程
3.2.2 工作原理
- 虚拟线程在载体线程上运行
- 当遇到阻塞操作时,虚拟线程会被挂起
- 载体线程被释放,可执行其他虚拟线程
- 阻塞操作完成后,虚拟线程在可用的载体线程上恢复执行
3.2.3 源码分析
java
// 虚拟线程创建
public final class Thread {
public static Thread startVirtualThread(Runnable task) {
Thread thread = Thread.ofVirtual().unstarted(task);
thread.start();
return thread;
}
}
// 虚拟线程调度器
class VirtualThreadScheduler {
void schedule(VirtualThread thread) {
// 选择载体线程
CarrierThread carrier = selectCarrierThread();
// 在载体线程上执行虚拟线程
carrier.execute(thread);
}
}
3.3 AOT 编译原理
3.3.1 实现机制
- 静态分析:编译时分析代码,确定依赖关系
- 字节码生成:生成优化的字节码,减少运行时开销
- 反射处理:提前处理反射,生成相应的代码
3.3.2 执行流程
- 编译时分析应用代码
- 生成 AOT 配置文件
- 编译 AOT 代码
- 构建时包含 AOT 生成的代码
3.3.3 源码分析
java
// AOT 编译核心类
public class AotProcessor {
public void process() {
// 1. 分析应用代码
analyzeApplication();
// 2. 生成 AOT 配置
generateAotConfig();
// 3. 编译 AOT 代码
compileAotCode();
}
}
3.4 内嵌容器原理
3.4.1 实现机制
- Tomcat:默认内嵌 Tomcat 服务器
- Jetty:可选内嵌 Jetty 服务器
- Undertow:可选内嵌 Undertow 服务器
3.4.2 启动流程
- Spring Boot 启动时,根据依赖自动选择内嵌容器
- 配置容器参数
- 启动容器
- 注册应用上下文
3.4.3 源码分析
java
// 内嵌容器自动配置
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
public class TomcatServletWebServerFactoryAutoConfiguration {
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory() {
return new TomcatServletWebServerFactory();
}
}
四、实践指南:Spring Boot 3 核心功能
4.1 项目初始化
4.1.1 使用 Spring Initializr
- 访问 https://start.spring.io/
- 选择 JDK 21、Spring Boot 3.2.4
- 添加所需依赖
- 生成并下载项目
4.1.2 手动配置 pom.xml
xml
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.4</version>
</parent>
<properties>
<java.version>21</java.version>
<mybatis.version>3.0.3</mybatis.version>
<redisson.version>3.27.0</redisson.version>
<lombok.version>1.18.30</lombok.version>
</properties>
<dependencies>
<!-- Web 核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 虚拟线程支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-virtual-threads</artifactId>
</dependency>
<!-- 数据库相关 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>8.4.3</version>
</dependency>
<!-- Redis 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redisson.version}</version>
</dependency>
<!-- MongoDB 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<!-- RabbitMQ 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- Elasticsearch 相关 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- 安全框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 接口文档 -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.3.0</version>
</dependency>
<!-- 开发工具 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
4.2 核心配置
4.2.1 应用配置(application.yml)
yaml
# 服务器配置
server:
port: 8080
tomcat:
threads:
# 启用虚拟线程
virtual: true
# Spring 配置
spring:
application:
name: springboot3-demo
4.2.2 环境配置
- application-dev.yml:开发环境配置
- application-prod.yml:生产环境配置
- application-test.yml:测试环境配置
4.3 RESTful API 开发
4.3.1 控制器
java
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping
public Result addUser(@RequestBody User user) {
// 业务逻辑
return Result.success(user);
}
@GetMapping("/{id}")
public Result getUserById(@PathVariable Long id) {
// 业务逻辑
return Result.success(user);
}
}
4.3.2 统一返回结果
java
// 统一返回接口
sealed interface Result permits SuccessResult, ErrorResult {
int getCode();
String getMsg();
}
// 成功返回
record SuccessResult<T>(int code, String msg, T data) implements Result {}
// 错误返回
record ErrorResult(int code, String msg) implements Result {}
// 返回工具类
public class ResultUtil {
// 成功返回
public static <T> Result success(T data) {
return new SuccessResult<>(200, "success", data);
}
// 错误返回
public static Result error(int code, String msg) {
return new ErrorResult(code, msg);
}
// 错误返回(默认错误码)
public static Result error(String msg) {
return new ErrorResult(500, msg);
}
}
五、中间件集成详解
5.1 MySQL + MyBatis 集成
5.1.1 配置
yaml
# 数据源配置
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/springboot3_demo?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
username: root
password: root
# MyBatis 配置
mybatis:
mapper-locations: classpath:mapper/**/*.xml
type-aliases-package: com.example.springboot3demo.entity
configuration:
map-underscore-to-camel-case: true
5.1.2 简单例子
步骤 1:创建实体类
java
// 用户实体类
@Data
public class User {
private Long id; // 用户ID
private String username; // 用户名
private String email; // 邮箱
}
步骤 2:创建 Mapper 接口
java
// UserMapper 接口
@Mapper
public interface UserMapper {
// 添加用户
int insert(User user);
// 根据ID查询用户
User selectById(Long id);
// 查询所有用户
List<User> selectAll();
}
步骤 3:创建映射文件
xml
<!-- UserMapper.xml -->
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springboot3demo.mapper.UserMapper">
<resultMap id="UserMap" type="com.example.springboot3demo.entity.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="email" property="email"/>
</resultMap>
<insert id="insert" parameterType="com.example.springboot3demo.entity.User">
INSERT INTO user (username, email)
VALUES (#{username}, #{email})
</insert>
<select id="selectById" parameterType="java.lang.Long" resultMap="UserMap">
SELECT * FROM user WHERE id = #{id}
</select>
<select id="selectAll" resultMap="UserMap">
SELECT * FROM user
</select>
</mapper>
步骤 4:创建服务层
java
// UserService 接口
public interface UserService {
// 添加用户
User addUser(User user);
// 根据ID查询用户
User getUserById(Long id);
// 查询所有用户
List<User> getAllUsers();
}
// UserService 实现类
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Override
public User addUser(User user) {
userMapper.insert(user);
return user;
}
@Override
public User getUserById(Long id) {
return userMapper.selectById(id);
}
@Override
public List<User> getAllUsers() {
return userMapper.selectAll();
}
}
步骤 5:创建控制器
java
// UserController
@RestController
@RequestMapping("/api/users")
public class UserController {
@Resource
private UserService userService;
// 添加用户
@PostMapping
public Result addUser(@RequestBody User user) {
User savedUser = userService.addUser(user);
return Result.success(savedUser);
}
// 根据ID查询用户
@GetMapping("/{id}")
public Result getUserById(@PathVariable Long id) {
User user = userService.getUserById(id);
return Result.success(user);
}
// 查询所有用户
@GetMapping
public Result getAllUsers() {
List<User> users = userService.getAllUsers();
return Result.success(users);
}
}
5.1.3 注解作用分析与原理
@Mapper 注解原理
- 作用:标记接口为 MyBatis 映射接口,MyBatis 会自动为其生成实现类
- 底层原理 :MyBatis 通过
MapperScannerConfigurer扫描带有@Mapper注解的接口,使用 JDK 动态代理为每个接口创建代理实现类。代理类会拦截方法调用,根据方法名和参数生成对应的 SQL 语句并执行。 - 实现机制 :
@Mapper注解被@MapperScan注解扫描- MyBatis 通过反射获取接口方法信息
- 使用动态代理创建接口实现
- 代理类根据方法名和参数生成 SQL 并执行
@Service 注解原理
- 作用:标记类为服务层组件,Spring 会自动扫描并注册为 Bean
- 底层原理 :Spring 通过组件扫描机制,识别带有
@Service注解的类,并将其注册到 Spring 容器中。@Service是@Component的特殊化,本质上是一个构造型注解。 - 实现机制 :
- Spring 启动时扫描指定包路径
- 识别带有
@Service注解的类 - 为这些类创建 Bean 定义
- 将 Bean 定义注册到 Spring 容器
@RestController 注解原理
- 作用 :组合注解,相当于
@Controller + @ResponseBody,用于 RESTful API - 底层原理 :
@RestController继承自@Controller,并添加了@ResponseBody注解。当方法返回值时,Spring 会自动将返回对象转换为 JSON 或 XML 格式。 - 实现机制 :
@RestController标记控制器类- 请求处理方法的返回值会被
HttpMessageConverter转换 - 转换后的结果直接写入 HTTP 响应体
@RequestMapping 注解原理
- 作用:映射 HTTP 请求路径
- 底层原理 :
@RequestMapping注解用于定义请求映射规则,Spring MVC 会根据这些规则将请求分发到对应的处理方法。 - 实现机制 :
- Spring 启动时解析
@RequestMapping注解 - 构建请求映射注册表
- 当请求到达时,根据 URL 和 HTTP 方法查找匹配的处理方法
- Spring 启动时解析
@PostMapping/@GetMapping 注解原理
- 作用:分别映射 POST 和 GET 请求
- 底层原理 :这些注解是
@RequestMapping的快捷方式,分别指定了 HTTP 方法为 POST 和 GET。 - 实现机制 :
@PostMapping相当于@RequestMapping(method = RequestMethod.POST)@GetMapping相当于@RequestMapping(method = RequestMethod.GET)
@PathVariable 注解原理
- 作用:获取 URL 路径参数
- 底层原理 :
@PathVariable注解用于绑定 URL 路径中的变量到方法参数。 - 实现机制 :
- Spring MVC 解析 URL 路径
- 提取路径中的变量值
- 将变量值绑定到方法参数
@RequestBody 注解原理
- 作用:将 HTTP 请求体转换为 Java 对象
- 底层原理 :
@RequestBody注解指示 Spring 从请求体中读取数据,并使用HttpMessageConverter将其转换为指定类型的对象。 - 实现机制 :
- Spring 从请求体中读取原始数据
- 根据请求的 Content-Type 选择合适的
HttpMessageConverter - 使用转换器将数据转换为目标对象
@Resource 注解原理
- 作用:依赖注入注解,默认按名称注入
- 底层原理 :
@Resource是 JSR-250 规范定义的注解,Spring 对其提供了支持。默认情况下,它会按照名称查找依赖对象。 - 实现机制 :
- Spring 解析
@Resource注解 - 首先按名称查找依赖对象
- 如果找不到,再按类型查找
- Spring 解析
@Data 注解原理
- 作用:Lombok 注解,自动生成 getter、setter、toString 等方法
- 底层原理 :Lombok 在编译时通过注解处理器为带有
@Data注解的类生成相应的方法。 - 实现机制 :
- 编译时 Lombok 注解处理器扫描
@Data注解 - 为类生成 getter、setter、toString、equals、hashCode 等方法
- 将生成的代码注入到编译后的字节码中
- 编译时 Lombok 注解处理器扫描
5.2 Redis 缓存集成
5.2.1 配置
yaml
# Redis 配置
spring:
redis:
host: localhost
port: 6379
password:
database: 0
lettuce:
pool:
max-active: 50
max-idle: 20
min-idle: 5
max-wait: 3000
5.2.2 简单例子
步骤 1:创建 Redis 服务
java
// Redis 缓存服务
@Service
public class RedisService {
@Resource
private RedisTemplate<String, Object> redisTemplate;
// 设置缓存
public void set(String key, Object value, long timeout, TimeUnit unit) {
redisTemplate.opsForValue().set(key, value, timeout, unit);
}
// 获取缓存
public Object get(String key) {
return redisTemplate.opsForValue().get(key);
}
// 删除缓存
public void delete(String key) {
redisTemplate.delete(key);
}
// 设置哈希值
public void hSet(String key, String field, Object value) {
redisTemplate.opsForHash().put(key, field, value);
}
// 获取哈希值
public Object hGet(String key, String field) {
return redisTemplate.opsForHash().get(key, field);
}
}
步骤 2:在服务中使用 Redis 缓存
java
// 在 UserService 中使用 Redis 缓存
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private RedisService redisService;
@Override
public User getUserById(Long id) {
// 先从缓存获取
String key = "user:" + id;
User user = (User) redisService.get(key);
if (user == null) {
// 缓存不存在,从数据库查询
user = userMapper.selectById(id);
// 设置缓存,过期时间 10 分钟
redisService.set(key, user, 10, TimeUnit.MINUTES);
}
return user;
}
}
5.2.3 注解作用分析与原理
@Service 注解原理
- 作用:标记类为服务层组件,Spring 会自动扫描并注册为 Bean
- 底层原理 :Spring 通过组件扫描机制,识别带有
@Service注解的类,并将其注册到 Spring 容器中。@Service是@Component的特殊化,本质上是一个构造型注解。 - 实现机制 :
- Spring 启动时扫描指定包路径
- 识别带有
@Service注解的类 - 为这些类创建 Bean 定义
- 将 Bean 定义注册到 Spring 容器
@Resource 注解原理
- 作用:依赖注入注解,默认按名称注入
- 底层原理 :
@Resource是 JSR-250 规范定义的注解,Spring 对其提供了支持。默认情况下,它会按照名称查找依赖对象。 - 实现机制 :
- Spring 解析
@Resource注解 - 首先按名称查找依赖对象
- 如果找不到,再按类型查找
- Spring 解析
RedisTemplate 原理
- 作用:Spring Data Redis 提供的核心模板类,用于操作 Redis
- 底层原理 :
RedisTemplate是 Spring Data Redis 的核心类,它封装了对 Redis 的各种操作,支持多种数据类型。 - 实现机制 :
RedisTemplate内部使用RedisConnectionFactory获取 Redis 连接- 通过序列化器将 Java 对象转换为 Redis 存储格式
- 提供了针对不同数据类型的操作方法(opsForValue、opsForHash、opsForList 等)
5.3 RabbitMQ 消息队列集成
5.3.1 配置
yaml
# RabbitMQ 配置
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: /
listener:
simple:
concurrency: 5
max-concurrency: 10
prefetch: 1
5.3.2 简单例子
步骤 1:创建消息发送服务
java
// 消息发送服务
@Service
public class RabbitMqService {
@Resource
private RabbitTemplate rabbitTemplate;
// 发送消息
public void sendMessage(String queueName, Object message) {
rabbitTemplate.convertAndSend(queueName, message);
}
// 发送消息到交换机
public void sendMessage(String exchange, String routingKey, Object message) {
rabbitTemplate.convertAndSend(exchange, routingKey, message);
}
}
步骤 2:创建消息监听器
java
// 消息监听器
@Component
public class RabbitMqListener {
@RabbitListener(queues = "userQueue")
public void handleUserMessage(User user) {
System.out.println("收到用户消息:" + user);
// 处理消息逻辑
}
@RabbitListener(queues = "orderQueue")
public void handleOrderMessage(Order order) {
System.out.println("收到订单消息:" + order);
// 处理消息逻辑
}
}
步骤 3:在服务中使用 RabbitMQ
java
// 在 UserService 中使用 RabbitMQ
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserMapper userMapper;
@Resource
private RabbitMqService rabbitMqService;
@Override
public User addUser(User user) {
userMapper.insert(user);
// 发送消息到队列
rabbitMqService.sendMessage("userQueue", user);
return user;
}
}
5.3.3 注解作用分析与原理
@Service 注解原理
- 作用:标记类为服务层组件,Spring 会自动扫描并注册为 Bean
- 底层原理 :Spring 通过组件扫描机制,识别带有
@Service注解的类,并将其注册到 Spring 容器中。@Service是@Component的特殊化,本质上是一个构造型注解。 - 实现机制 :
- Spring 启动时扫描指定包路径
- 识别带有
@Service注解的类 - 为这些类创建 Bean 定义
- 将 Bean 定义注册到 Spring 容器
@Component 注解原理
- 作用:标记类为 Spring 组件,Spring 会自动扫描并注册为 Bean
- 底层原理 :
@Component是 Spring 组件扫描的基础注解,用于标记一个类为 Spring 管理的组件。 - 实现机制 :
- Spring 启动时扫描指定包路径
- 识别带有
@Component注解的类 - 为这些类创建 Bean 定义
- 将 Bean 定义注册到 Spring 容器
@RabbitListener 注解原理
- 作用:标记方法为 RabbitMQ 消息监听器,用于接收指定队列的消息
- 底层原理 :
@RabbitListener注解由 Spring AMQP 提供,用于声明一个方法作为 RabbitMQ 消息的监听器。 - 实现机制 :
- Spring 启动时解析
@RabbitListener注解 - 为每个注解创建一个消息监听器容器
- 容器监听指定的队列
- 当消息到达时,调用注解标记的方法处理消息
- Spring 启动时解析
RabbitTemplate 原理
- 作用:Spring AMQP 提供的核心模板类,用于发送消息
- 底层原理 :
RabbitTemplate是 Spring AMQP 的核心类,它封装了与 RabbitMQ 服务器的通信逻辑。 - 实现机制 :
RabbitTemplate内部使用ConnectionFactory获取 RabbitMQ 连接- 创建消息并设置相关属性
- 将消息发送到指定的交换机或队列
- 处理消息发送的确认和返回
5.4 MongoDB 文档数据库集成
5.4.1 配置
yaml
# MongoDB 配置
spring:
data:
mongodb:
uri: mongodb://localhost:27017/springboot3_demo
5.4.2 简单例子
步骤 1:创建实体类
java
// MongoDB 实体类
@Document(collection = "products")
@Data
public class Product {
@Id
private String id;
private String name;
private double price;
private String description;
private LocalDateTime createTime;
}
步骤 2:创建仓库接口
java
// MongoDB 仓库
public interface ProductRepository extends MongoRepository<Product, String> {
List<Product> findByName(String name);
List<Product> findByPriceGreaterThan(double price);
List<Product> findByNameContaining(String keyword);
}
步骤 3:创建服务层
java
// MongoDB 服务
@Service
public class ProductService {
@Resource
private ProductRepository productRepository;
public Product save(Product product) {
product.setCreateTime(LocalDateTime.now());
return productRepository.save(product);
}
public Product findById(String id) {
return productRepository.findById(id).orElse(null);
}
public List<Product> findAll() {
return productRepository.findAll();
}
public List<Product> findByName(String name) {
return productRepository.findByName(name);
}
public List<Product> findByPriceGreaterThan(double price) {
return productRepository.findByPriceGreaterThan(price);
}
}
步骤 4:创建控制器
java
// ProductController
@RestController
@RequestMapping("/api/products")
public class ProductController {
@Resource
private ProductService productService;
// 添加产品
@PostMapping
public Result addProduct(@RequestBody Product product) {
Product savedProduct = productService.save(product);
return Result.success(savedProduct);
}
// 根据ID查询产品
@GetMapping("/{id}")
public Result getProductById(@PathVariable String id) {
Product product = productService.findById(id);
return Result.success(product);
}
// 查询所有产品
@GetMapping
public Result getAllProducts() {
List<Product> products = productService.findAll();
return Result.success(products);
}
// 根据名称查询产品
@GetMapping("/name/{name}")
public Result getProductsByName(@PathVariable String name) {
List<Product> products = productService.findByName(name);
return Result.success(products);
}
}
5.4.3 注解作用分析与原理
@Document 注解原理
- 作用:标记类为 MongoDB 文档实体,指定集合名称
- 底层原理 :
@Document注解由 Spring Data MongoDB 提供,用于将 Java 类映射到 MongoDB 集合。 - 实现机制 :
- Spring Data MongoDB 扫描带有
@Document注解的类 - 建立 Java 类与 MongoDB 集合的映射关系
- 基于注解配置生成相应的文档操作
- Spring Data MongoDB 扫描带有
@Id 注解原理
- 作用:标记字段为文档 ID
- 底层原理 :
@Id注解用于指定 MongoDB 文档的 _id 字段。 - 实现机制 :
- Spring Data MongoDB 识别带有
@Id注解的字段 - 将该字段映射到 MongoDB 文档的 _id 字段
- 支持自动生成 ID(如 ObjectId)
- Spring Data MongoDB 识别带有
@Service 注解原理
- 作用:标记类为服务层组件,Spring 会自动扫描并注册为 Bean
- 底层原理 :Spring 通过组件扫描机制,识别带有
@Service注解的类,并将其注册到 Spring 容器中。@Service是@Component的特殊化,本质上是一个构造型注解。 - 实现机制 :
- Spring 启动时扫描指定包路径
- 识别带有
@Service注解的类 - 为这些类创建 Bean 定义
- 将 Bean 定义注册到 Spring 容器
@RestController 注解原理
- 作用 :组合注解,相当于
@Controller + @ResponseBody,用于 RESTful API - 底层原理 :
@RestController继承自@Controller,并添加了@ResponseBody注解。当方法返回值时,Spring 会自动将返回对象转换为 JSON 或 XML 格式。 - 实现机制 :
@RestController标记控制器类- 请求处理方法的返回值会被
HttpMessageConverter转换 - 转换后的结果直接写入 HTTP 响应体
@RequestMapping 注解原理
- 作用:映射 HTTP 请求路径
- 底层原理 :
@RequestMapping注解用于定义请求映射规则,Spring MVC 会根据这些规则将请求分发到对应的处理方法。 - 实现机制 :
- Spring 启动时解析
@RequestMapping注解 - 构建请求映射注册表
- 当请求到达时,根据 URL 和 HTTP 方法查找匹配的处理方法
- Spring 启动时解析
@PostMapping/@GetMapping 注解原理
- 作用:分别映射 POST 和 GET 请求
- 底层原理 :这些注解是
@RequestMapping的快捷方式,分别指定了 HTTP 方法为 POST 和 GET。 - 实现机制 :
@PostMapping相当于@RequestMapping(method = RequestMethod.POST)@GetMapping相当于@RequestMapping(method = RequestMethod.GET)
@PathVariable 注解原理
- 作用:获取 URL 路径参数
- 底层原理 :
@PathVariable注解用于绑定 URL 路径中的变量到方法参数。 - 实现机制 :
- Spring MVC 解析 URL 路径
- 提取路径中的变量值
- 将变量值绑定到方法参数
@RequestBody 注解原理
- 作用:将 HTTP 请求体转换为 Java 对象
- 底层原理 :
@RequestBody注解指示 Spring 从请求体中读取数据,并使用HttpMessageConverter将其转换为指定类型的对象。 - 实现机制 :
- Spring 从请求体中读取原始数据
- 根据请求的 Content-Type 选择合适的
HttpMessageConverter - 使用转换器将数据转换为目标对象
@Resource 注解原理
- 作用:依赖注入注解,默认按名称注入
- 底层原理 :
@Resource是 JSR-250 规范定义的注解,Spring 对其提供了支持。默认情况下,它会按照名称查找依赖对象。 - 实现机制 :
- Spring 解析
@Resource注解 - 首先按名称查找依赖对象
- 如果找不到,再按类型查找
- Spring 解析
@Data 注解原理
- 作用:Lombok 注解,自动生成 getter、setter、toString 等方法
- 底层原理 :Lombok 在编译时通过注解处理器为带有
@Data注解的类生成相应的方法。 - 实现机制 :
- 编译时 Lombok 注解处理器扫描
@Data注解 - 为类生成 getter、setter、toString、equals、hashCode 等方法
- 将生成的代码注入到编译后的字节码中
- 编译时 Lombok 注解处理器扫描
MongoRepository 原理
- 作用:Spring Data MongoDB 提供的仓库接口,自动实现 CRUD 操作
- 底层原理 :
MongoRepository是 Spring Data MongoDB 的核心接口,它提供了基本的 CRUD 操作方法。 - 实现机制 :
- Spring Data MongoDB 为
MongoRepository的子接口生成实现类 - 根据方法名自动生成查询语句
- 支持自定义查询方法和复杂查询
- Spring Data MongoDB 为
5.5 Elasticsearch 搜索引擎集成
5.5.1 配置
yaml
# Elasticsearch 配置
spring:
elasticsearch:
uris: http://localhost:9200
username: elastic
password: changeme
5.5.2 简单例子
步骤 1:创建实体类
java
// Elasticsearch 实体类
@Document(indexName = "articles")
@Data
public class Article {
@Id
private String id;
private String title;
private String content;
private String author;
private LocalDateTime createTime;
}
步骤 2:创建仓库接口
java
// Elasticsearch 仓库
public interface ArticleRepository extends ElasticsearchRepository<Article, String> {
List<Article> findByTitleContainingOrContentContaining(String title, String content);
List<Article> findByAuthor(String author);
}
步骤 3:创建服务层
java
// Elasticsearch 服务
@Service
public class ArticleService {
@Resource
private ArticleRepository articleRepository;
public Article save(Article article) {
article.setCreateTime(LocalDateTime.now());
return articleRepository.save(article);
}
public Article findById(String id) {
return articleRepository.findById(id).orElse(null);
}
public List<Article> search(String keyword) {
return articleRepository.findByTitleContainingOrContentContaining(keyword, keyword);
}
public List<Article> findByAuthor(String author) {
return articleRepository.findByAuthor(author);
}
}
步骤 4:创建控制器
java
// ArticleController
@RestController
@RequestMapping("/api/articles")
public class ArticleController {
@Resource
private ArticleService articleService;
// 添加文章
@PostMapping
public Result addArticle(@RequestBody Article article) {
Article savedArticle = articleService.save(article);
return Result.success(savedArticle);
}
// 根据ID查询文章
@GetMapping("/{id}")
public Result getArticleById(@PathVariable String id) {
Article article = articleService.findById(id);
return Result.success(article);
}
// 搜索文章
@GetMapping("/search")
public Result searchArticles(@RequestParam String keyword) {
List<Article> articles = articleService.search(keyword);
return Result.success(articles);
}
// 根据作者查询文章
@GetMapping("/author/{author}")
public Result getArticlesByAuthor(@PathVariable String author) {
List<Article> articles = articleService.findByAuthor(author);
return Result.success(articles);
}
}
5.5.3 注解作用分析与原理
@Document 注解原理
- 作用:标记类为 Elasticsearch 文档实体,指定索引名称
- 底层原理 :
@Document注解由 Spring Data Elasticsearch 提供,用于将 Java 类映射到 Elasticsearch 索引。 - 实现机制 :
- Spring Data Elasticsearch 扫描带有
@Document注解的类 - 建立 Java 类与 Elasticsearch 索引的映射关系
- 基于注解配置生成相应的文档操作
- Spring Data Elasticsearch 扫描带有
@Id 注解原理
- 作用:标记字段为文档 ID
- 底层原理 :
@Id注解用于指定 Elasticsearch 文档的 _id 字段。 - 实现机制 :
- Spring Data Elasticsearch 识别带有
@Id注解的字段 - 将该字段映射到 Elasticsearch 文档的 _id 字段
- 支持自动生成 ID
- Spring Data Elasticsearch 识别带有
@Service 注解原理
- 作用:标记类为服务层组件,Spring 会自动扫描并注册为 Bean
- 底层原理 :Spring 通过组件扫描机制,识别带有
@Service注解的类,并将其注册到 Spring 容器中。@Service是@Component的特殊化,本质上是一个构造型注解。 - 实现机制 :
- Spring 启动时扫描指定包路径
- 识别带有
@Service注解的类 - 为这些类创建 Bean 定义
- 将 Bean 定义注册到 Spring 容器
@RestController 注解原理
- 作用 :组合注解,相当于
@Controller + @ResponseBody,用于 RESTful API - 底层原理 :
@RestController继承自@Controller,并添加了@ResponseBody注解。当方法返回值时,Spring 会自动将返回对象转换为 JSON 或 XML 格式。 - 实现机制 :
@RestController标记控制器类- 请求处理方法的返回值会被
HttpMessageConverter转换 - 转换后的结果直接写入 HTTP 响应体
@RequestMapping 注解原理
- 作用:映射 HTTP 请求路径
- 底层原理 :
@RequestMapping注解用于定义请求映射规则,Spring MVC 会根据这些规则将请求分发到对应的处理方法。 - 实现机制 :
- Spring 启动时解析
@RequestMapping注解 - 构建请求映射注册表
- 当请求到达时,根据 URL 和 HTTP 方法查找匹配的处理方法
- Spring 启动时解析
@PostMapping/@GetMapping 注解原理
- 作用:分别映射 POST 和 GET 请求
- 底层原理 :这些注解是
@RequestMapping的快捷方式,分别指定了 HTTP 方法为 POST 和 GET。 - 实现机制 :
@PostMapping相当于@RequestMapping(method = RequestMethod.POST)@GetMapping相当于@RequestMapping(method = RequestMethod.GET)
@PathVariable 注解原理
- 作用:获取 URL 路径参数
- 底层原理 :
@PathVariable注解用于绑定 URL 路径中的变量到方法参数。 - 实现机制 :
- Spring MVC 解析 URL 路径
- 提取路径中的变量值
- 将变量值绑定到方法参数
@RequestParam 注解原理
- 作用:获取 URL 查询参数
- 底层原理 :
@RequestParam注解用于绑定 URL 查询参数到方法参数。 - 实现机制 :
- Spring MVC 解析 URL 查询字符串
- 提取查询参数的值
- 将参数值绑定到方法参数
@RequestBody 注解原理
- 作用:将 HTTP 请求体转换为 Java 对象
- 底层原理 :
@RequestBody注解指示 Spring 从请求体中读取数据,并使用HttpMessageConverter将其转换为指定类型的对象。 - 实现机制 :
- Spring 从请求体中读取原始数据
- 根据请求的 Content-Type 选择合适的
HttpMessageConverter - 使用转换器将数据转换为目标对象
@Resource 注解原理
- 作用:依赖注入注解,默认按名称注入
- 底层原理 :
@Resource是 JSR-250 规范定义的注解,Spring 对其提供了支持。默认情况下,它会按照名称查找依赖对象。 - 实现机制 :
- Spring 解析
@Resource注解 - 首先按名称查找依赖对象
- 如果找不到,再按类型查找
- Spring 解析
@Data 注解原理
- 作用:Lombok 注解,自动生成 getter、setter、toString 等方法
- 底层原理 :Lombok 在编译时通过注解处理器为带有
@Data注解的类生成相应的方法。 - 实现机制 :
- 编译时 Lombok 注解处理器扫描
@Data注解 - 为类生成 getter、setter、toString、equals、hashCode 等方法
- 将生成的代码注入到编译后的字节码中
- 编译时 Lombok 注解处理器扫描
ElasticsearchRepository 原理
- 作用:Spring Data Elasticsearch 提供的仓库接口,自动实现搜索操作
- 底层原理 :
ElasticsearchRepository是 Spring Data Elasticsearch 的核心接口,它提供了基本的 CRUD 操作和搜索方法。 - 实现机制 :
- Spring Data Elasticsearch 为
ElasticsearchRepository的子接口生成实现类 - 根据方法名自动生成查询语句
- 支持复杂的搜索操作和聚合查询
- Spring Data Elasticsearch 为
5.6 PostgreSQL 关系型数据库集成
5.6.1 配置
yaml
# PostgreSQL 配置
spring:
datasource:
driver-class-name: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/springboot3_demo
username: postgres
password: postgres
# JPA 配置
spring:
jpa:
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
5.6.2 简单例子
步骤 1:创建实体类
java
// PostgreSQL 实体类
@Entity
@Table(name = "users")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "username", nullable = false, unique = true)
private String username;
@Column(name = "email", nullable = false, unique = true)
private String email;
@Column(name = "create_time")
private LocalDateTime createTime;
@PrePersist
public void prePersist() {
createTime = LocalDateTime.now();
}
}
步骤 2:创建仓库接口
java
// PostgreSQL 仓库
public interface UserRepository extends JpaRepository<User, Long> {
User findByUsername(String username);
User findByEmail(String email);
List<User> findByUsernameContaining(String keyword);
}
步骤 3:创建服务层
java
// PostgreSQL 服务
@Service
public class UserService {
@Resource
private UserRepository userRepository;
public User save(User user) {
return userRepository.save(user);
}
public User findById(Long id) {
return userRepository.findById(id).orElse(null);
}
public User findByUsername(String username) {
return userRepository.findByUsername(username);
}
public List<User> findByUsernameContaining(String keyword) {
return userRepository.findByUsernameContaining(keyword);
}
public List<User> findAll() {
return userRepository.findAll();
}
}
步骤 4:创建控制器
java
// UserController
@RestController
@RequestMapping("/api/users")
public class UserController {
@Resource
private UserService userService;
// 添加用户
@PostMapping
public Result addUser(@RequestBody User user) {
User savedUser = userService.save(user);
return Result.success(savedUser);
}
// 根据ID查询用户
@GetMapping("/{id}")
public Result getUserById(@PathVariable Long id) {
User user = userService.findById(id);
return Result.success(user);
}
// 根据用户名查询用户
@GetMapping("/username/{username}")
public Result getUserByUsername(@PathVariable String username) {
User user = userService.findByUsername(username);
return Result.success(user);
}
// 搜索用户
@GetMapping("/search")
public Result searchUsers(@RequestParam String keyword) {
List<User> users = userService.findByUsernameContaining(keyword);
return Result.success(users);
}
// 查询所有用户
@GetMapping
public Result getAllUsers() {
List<User> users = userService.findAll();
return Result.success(users);
}
}
5.6.3 注解作用分析与原理
@Entity 注解原理
- 作用:标记类为 JPA 实体类
- 底层原理 :
@Entity注解由 JPA 规范定义,用于将 Java 类映射到数据库表。 - 实现机制 :
- JPA 扫描带有
@Entity注解的类 - 建立 Java 类与数据库表的映射关系
- 基于注解配置生成相应的 SQL 语句
- JPA 扫描带有
@Table 注解原理
- 作用:指定实体类对应的数据库表名
- 底层原理 :
@Table注解用于自定义实体类与数据库表的映射关系。 - 实现机制 :
- JPA 解析
@Table注解 - 使用指定的表名进行数据库操作
- JPA 解析
@Id 注解原理
- 作用:标记字段为实体的主键
- 底层原理 :
@Id注解用于指定实体的主键字段。 - 实现机制 :
- JPA 识别带有
@Id注解的字段 - 将该字段映射到数据库表的主键列
- JPA 识别带有
@GeneratedValue 注解原理
- 作用:指定主键的生成策略
- 底层原理 :
@GeneratedValue注解用于指定主键的生成方式。 - 实现机制 :
- JPA 根据指定的策略生成主键值
- 支持 IDENTITY、SEQUENCE、TABLE、AUTO 等策略
@Column 注解原理
- 作用:指定字段对应的数据库列属性
- 底层原理 :
@Column注解用于自定义字段与数据库列的映射关系。 - 实现机制 :
- JPA 解析
@Column注解 - 根据注解配置生成相应的列定义
- JPA 解析
@PrePersist 注解原理
- 作用:在实体持久化前执行的方法
- 底层原理 :
@PrePersist注解用于标记在实体保存到数据库之前执行的方法。 - 实现机制 :
- JPA 在保存实体前检测
@PrePersist注解 - 执行注解标记的方法
- JPA 在保存实体前检测
JpaRepository 原理
- 作用:Spring Data JPA 提供的仓库接口,自动实现 CRUD 操作
- 底层原理 :
JpaRepository是 Spring Data JPA 的核心接口,它提供了基本的 CRUD 操作方法。 - 实现机制 :
- Spring Data JPA 为
JpaRepository的子接口生成实现类 - 根据方法名自动生成查询语句
- 支持复杂的查询和分页操作
- Spring Data JPA 为
5.7 Kafka 消息队列集成
5.7.1 配置
yaml
# Kafka 配置
spring:
kafka:
bootstrap-servers: localhost:9092
producer:
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-serializer: org.springframework.kafka.support.serializer.JsonSerializer
consumer:
group-id: springboot3-demo-group
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
properties:
spring:
json:
trusted:
packages: com.example.springboot3demo.entity
5.7.2 简单例子
步骤 1:创建消息实体类
java
// Kafka 消息实体类
@Data
public class OrderMessage {
private Long orderId;
private String orderName;
private double amount;
private LocalDateTime createTime;
}
步骤 2:创建消息发送服务
java
// Kafka 消息发送服务
@Service
public class KafkaService {
@Resource
private KafkaTemplate<String, Object> kafkaTemplate;
// 发送消息
public void sendMessage(String topic, Object message) {
kafkaTemplate.send(topic, message);
}
// 发送消息(带回调)
public void sendMessageWithCallback(String topic, Object message) {
kafkaTemplate.send(topic, message).addCallback(
success -> System.out.println("消息发送成功: " + success.getRecordMetadata()),
failure -> System.err.println("消息发送失败: " + failure.getMessage())
);
}
}
步骤 3:创建消息监听器
java
// Kafka 消息监听器
@Component
public class KafkaListener {
@org.springframework.kafka.annotation.KafkaListener(topics = "order-topic", groupId = "springboot3-demo-group")
public void handleOrderMessage(OrderMessage orderMessage) {
System.out.println("收到订单消息:" + orderMessage);
// 处理消息逻辑
}
@org.springframework.kafka.annotation.KafkaListener(topics = "user-topic", groupId = "springboot3-demo-group")
public void handleUserMessage(User user) {
System.out.println("收到用户消息:" + user);
// 处理消息逻辑
}
}
步骤 4:在服务中使用 Kafka
java
// 在 OrderService 中使用 Kafka
@Service
public class OrderService {
@Resource
private KafkaService kafkaService;
public Order createOrder(Order order) {
// 创建订单逻辑
// 发送订单消息
OrderMessage orderMessage = new OrderMessage();
orderMessage.setOrderId(order.getId());
orderMessage.setOrderName(order.getName());
orderMessage.setAmount(order.getAmount());
orderMessage.setCreateTime(LocalDateTime.now());
kafkaService.sendMessage("order-topic", orderMessage);
return order;
}
}
5.7.3 注解作用分析与原理
@Service 注解原理
- 作用:标记类为服务层组件,Spring 会自动扫描并注册为 Bean
- 底层原理 :Spring 通过组件扫描机制,识别带有
@Service注解的类,并将其注册到 Spring 容器中。@Service是@Component的特殊化,本质上是一个构造型注解。 - 实现机制 :
- Spring 启动时扫描指定包路径
- 识别带有
@Service注解的类 - 为这些类创建 Bean 定义
- 将 Bean 定义注册到 Spring 容器
@Component 注解原理
- 作用:标记类为 Spring 组件,Spring 会自动扫描并注册为 Bean
- 底层原理 :
@Component是 Spring 组件扫描的基础注解,用于标记一个类为 Spring 管理的组件。 - 实现机制 :
- Spring 启动时扫描指定包路径
- 识别带有
@Component注解的类 - 为这些类创建 Bean 定义
- 将 Bean 定义注册到 Spring 容器
@KafkaListener 注解原理
- 作用:标记方法为 Kafka 消息监听器,用于接收指定主题的消息
- 底层原理 :
@KafkaListener注解由 Spring Kafka 提供,用于声明一个方法作为 Kafka 消息的监听器。 - 实现机制 :
- Spring 启动时解析
@KafkaListener注解 - 为每个注解创建一个消息监听器容器
- 容器监听指定的主题
- 当消息到达时,调用注解标记的方法处理消息
- Spring 启动时解析
KafkaTemplate 原理
- 作用:Spring Kafka 提供的核心模板类,用于发送消息
- 底层原理 :
KafkaTemplate是 Spring Kafka 的核心类,它封装了与 Kafka 服务器的通信逻辑。 - 实现机制 :
KafkaTemplate内部使用ProducerFactory创建 Kafka 生产者- 创建消息并设置相关属性
- 将消息发送到指定的主题
- 处理消息发送的确认和回调
5.8 Nginx 反向代理集成
5.8.1 配置
Nginx 配置文件
nginx
# Nginx 配置
server {
listen 80;
server_name localhost;
# 静态资源
location /static/ {
root /path/to/your/project;
expires 30d;
}
# API 代理
location /api/ {
proxy_pass http://localhost:8080/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 根路径
location / {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Spring Boot 配置
yaml
# 服务器配置
server:
port: 8080
servlet:
context-path: /
# Tomcat 配置
server:
tomcat:
remote-ip-header: X-Forwarded-For
protocol-header: X-Forwarded-Proto
port-header: X-Forwarded-Port
5.8.2 简单例子
步骤 1:配置 Nginx
- 安装 Nginx
- 创建配置文件(如上)
- 启动 Nginx 服务
步骤 2:配置 Spring Boot 应用
- 添加服务器配置(如上)
- 启动 Spring Boot 应用
步骤 3:测试访问
- 通过 Nginx 访问应用:http://localhost/
- 通过 Nginx 访问 API:http://localhost/api/users
5.8.3 配置原理
Nginx 反向代理原理
- 作用:将客户端请求转发到后端服务器,并将后端服务器的响应返回给客户端
- 底层原理:Nginx 作为反向代理服务器,接收客户端请求,根据配置将请求转发到相应的后端服务器,然后将后端服务器的响应返回给客户端。
- 实现机制 :
- Nginx 监听指定端口
- 接收客户端请求
- 根据 location 配置匹配请求路径
- 将请求转发到配置的后端服务器
- 接收后端服务器的响应
- 将响应返回给客户端
Spring Boot 与 Nginx 集成原理
- 作用:通过 Nginx 反向代理访问 Spring Boot 应用
- 底层原理:Spring Boot 应用作为后端服务器,Nginx 作为前端代理,处理静态资源和请求转发。
- 实现机制 :
- Nginx 处理静态资源请求
- 将 API 请求转发到 Spring Boot 应用
- Spring Boot 应用处理业务逻辑
- Nginx 将 Spring Boot 应用的响应返回给客户端
5.9 分布式追踪(Zipkin + Sleuth)集成
5.9.1 配置
yaml
# Zipkin + Sleuth 配置
spring:
sleuth:
sampler:
probability: 1.0 # 采样率,生产环境建议设置为 0.1
zipkin:
base-url: http://localhost:9411/ # Zipkin 服务器地址
5.9.2 简单例子
步骤 1:启动 Zipkin 服务器
bash
# 启动 Zipkin 服务器
java -jar zipkin-server-2.24.3-exec.jar
步骤 2:创建服务间调用
服务 A
java
// ServiceAController
@RestController
@RequestMapping("/api/service-a")
public class ServiceAController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/call-service-b")
public Result callServiceB() {
// 调用服务 B
String url = "http://localhost:8081/api/service-b/hello";
String response = restTemplate.getForObject(url, String.class);
return Result.success("Service A called Service B: " + response);
}
}
服务 B
java
// ServiceBController
@RestController
@RequestMapping("/api/service-b")
public class ServiceBController {
@GetMapping("/hello")
public String hello() {
return "Hello from Service B";
}
}
步骤 3:测试分布式追踪
- 启动服务 A 和服务 B
- 访问服务 A 的接口:http://localhost:8080/api/service-a/call-service-b
- 打开 Zipkin 界面:http://localhost:9411/
- 查看服务调用链路
5.9.3 原理分析
Sleuth 原理
- 作用:为分布式系统中的服务调用添加追踪信息
- 底层原理:Sleuth 通过在服务调用过程中添加跟踪 ID 和跨度 ID,实现对分布式系统的调用链路追踪。
- 实现机制 :
- Sleuth 为每个服务调用生成唯一的跟踪 ID
- 在服务间调用时传递跟踪 ID
- 记录每个服务的处理时间和状态
- 将追踪信息发送到 Zipkin 服务器
Zipkin 原理
- 作用:收集、存储和展示分布式系统的调用链路信息
- 底层原理:Zipkin 作为分布式追踪系统,接收并存储来自各服务的追踪信息,提供可视化的调用链路展示。
- 实现机制 :
- 接收来自 Sleuth 的追踪信息
- 存储追踪数据
- 提供 Web 界面展示调用链路
- 支持查询和分析调用链路
5.10 监控系统(Prometheus + Grafana)集成
5.10.1 配置
Spring Boot 配置
yaml
# Actuator 配置
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
metrics:
export:
prometheus:
enabled: true
# Prometheus 配置
spring:
application:
name: springboot3-demo
Prometheus 配置文件
yaml
# prometheus.yml
scrape_configs:
- job_name: 'springboot3-demo'
metrics_path: '/actuator/prometheus'
scrape_interval: 5s
static_configs:
- targets: ['localhost:8080']
5.10.2 简单例子
步骤 1:启动 Prometheus
- 下载并安装 Prometheus
- 创建配置文件(如上)
- 启动 Prometheus 服务
步骤 2:启动 Grafana
- 下载并安装 Grafana
- 启动 Grafana 服务
步骤 3:配置 Grafana
- 登录 Grafana:http://localhost:3000/
- 添加 Prometheus 数据源
- 导入 Spring Boot 监控仪表盘(ID: 12856)
步骤 4:测试监控
- 启动 Spring Boot 应用
- 访问应用接口,产生一些流量
- 打开 Grafana 仪表盘查看监控数据
5.10.3 原理分析
Actuator 原理
- 作用:提供 Spring Boot 应用的监控和管理端点
- 底层原理:Actuator 通过暴露一系列 REST 端点,提供应用的健康状态、指标、环境信息等。
- 实现机制 :
- Actuator 自动配置各种监控端点
- 暴露 REST 接口供外部访问
- 收集应用的运行状态和指标
Prometheus 原理
- 作用:收集和存储时间序列数据
- 底层原理:Prometheus 通过定期抓取目标应用的指标端点,收集和存储时间序列数据。
- 实现机制 :
- 配置抓取目标和间隔
- 定期访问目标应用的指标端点
- 解析和存储指标数据
- 提供查询语言和 API
Grafana 原理
- 作用:可视化展示监控数据
- 底层原理:Grafana 通过连接各种数据源,提供丰富的可视化图表和仪表盘。
- 实现机制 :
- 连接 Prometheus 等数据源
- 提供拖拽式仪表盘构建
- 支持多种图表类型
- 提供告警功能
六、生产部署
6.1 打包配置
xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
6.2 Docker 部署
dockerfile
FROM eclipse-temurin:21-jdk-alpine
WORKDIR /app
COPY target/springboot3-demo.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
6.3 性能优化
yaml
# 数据库连接池优化
spring:
datasource:
hikari:
maximum-pool-size: 50
minimum-idle: 10
idle-timeout: 600000
max-lifetime: 1800000
connection-timeout: 30000
# Redis 连接池优化
spring:
redis:
lettuce:
pool:
max-active: 50
max-idle: 20
min-idle: 5
max-wait: 3000
# JVM 调优
# -XX:+EnableVirtualThreads
# -XX:+UseZGC
# -Xmx2g
五、核心总结
5.1 Spring Boot 3 核心优势
- 简化配置:自动配置减少手动配置
- 提升性能:虚拟线程、AOT 编译、ZGC
- 现代化 API:Jakarta EE 10、JDK 21 特性
- 简化开发:起步依赖、DevTools、Actuator
- 易于部署:内嵌容器、Docker 支持
5.2 最佳实践
- 使用虚拟线程:高并发场景性能提升
- 合理配置:根据实际需求配置连接池、线程池
- 监控运维:使用 Actuator 进行监控
- 安全配置:配置 HTTPS、密码加密
- 持续集成:使用 CI/CD 流程
5.3 学习路径
- 基础阶段:Spring Boot 核心概念、RESTful API 开发
- 进阶阶段:数据访问、缓存、消息队列
- 高级阶段:性能优化、生产部署、微服务
- 专家阶段:源码分析、自定义自动配置