1.如何配置开发环境(JDK、Maven、IDEA等);
2.如何快速搭建SpringBoot项目;
3.如何在SpringBoot中整合持久层框架(Mabatis、Mabatis-Plus、JPA等);
4.如何进行数据缓存管理。
5.如何使用Thymeleaf进行视图开发。
6.如何进行权限控制和安全控制。
7.消息服务和任务管理。
8.完整的项目开发流程等。
① 如何配置开发环境(JDK、Maven、IDEA等)
-
一、JDK 17(LTS)安装与配置
JDK 是 Java 开发的核心,推荐安装长期支持版(LTS)的 JDK 17。
1. 下载 JDK
- 官方推荐渠道:
- Eclipse Temurin(Adoptium)(开源免费,广泛使用)
- Oracle JDK(需注册账号,商用可能收费)
- 选择对应系统版本:
- Windows:
x64架构的.msi(傻瓜式安装)或.zip(手动解压) - macOS:
x64或aarch64(M1/M2 芯片)的.pkg或.tar.gz
- Windows:
-
配置开发环境的核心步骤:
- 安装 JDK 并配置
JAVA_HOME,确保java -version正常。 - 安装 Maven 并配置镜像和本地仓库,确保
mvn -v正常。 - 在 IDEA 中关联 JDK 和 Maven,安装必要插件,配置编码。
四、验证开发环境
- 打开 IDEA → 点击 “New Project” → 选择 “Spring Initializr” → 选择 JDK 17 → 填写项目信息(Group、Artifact) → 勾选 “Spring Web” 依赖 → 点击 “Create”。
- 新建一个 Controller 类:
java
运行
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @GetMapping("/test") public String test() { return "Hello, Dev Environment!"; } } - 运行项目的主启动类 → 访问
http://localhost:8080/test,若返回字符串则环境配置成功。 -
5. 配置编码格式(避免中文乱码)
- 进入 “File → Settings → Editor → File Encodings”。
- 全部设置为 “UTF-8”:
- Global Encoding: UTF-8
- Project Encoding: UTF-8
- Default encoding for properties files: UTF-8
- 勾选 “Transparent native-to-ascii conversion”。
-
4. 安装必要插件
- 进入 “File → Settings → Plugins”。
- 搜索并安装以下插件:
- Spring Boot DevTools:支持热部署,修改代码后无需重启应用。
- Spring Initializr and Assistant:快速创建 Spring Boot 项目。
- Thymeleaf:Thymeleaf 模板语法高亮和提示。
- Lombok:简化实体类代码(需配合 Lombok 依赖使用)。
- MyBatisX:MyBatis 框架的 XML 映射文件和接口跳转支持。
-
3. 配置 Maven
- 进入 “File → Settings”(Windows/Linux)或 “IntelliJ IDEA → Settings”(macOS)。
- 搜索 “Maven” → 配置以下参数:
- “Maven home path”:选择 Maven 安装目录(如
D:\dev\apache-maven-3.9.6)。 - “User settings file”:选择 Maven 的
conf/settings.xml(启用 “Override” 后选择)。 - “Local repository”:自动读取 settings.xml 中的本地仓库路径,无需手动修改。
- “Maven home path”:选择 Maven 安装目录(如
- 点击 “Apply → OK” 生效。
-
2. 配置 JDK
- 打开 IDEA → 进入 “File → Project Structure”(或新建项目时)。
- 在 “SDKs” 选项卡 → 点击 “+” → “Add JDK” → 选择已安装的 JDK 17 路径(如
C:\Program Files\Eclipse Adoptium\jdk-17.0.10+7) → 点击 “OK”。 - 设为默认 JDK:在 “Project” 选项卡中,将 “Project SDK” 选为 JDK 17。
-
1. 下载与安装 IDEA
- 访问JetBrains 官网,选择 “Community Edition”(社区版)下载。
- 安装时勾选:
- “Create Desktop Shortcut”(创建桌面快捷方式)
- “Add launchers dir to PATH”(可选,便于命令行启动)
- 关联
.java等文件(根据需求勾选)。
-
三、IntelliJ IDEA 配置
IDEA 是主流的 Java IDE,社区版(Community)免费,功能足够开发 Spring Boot 项目。
5. 验证 Maven 安装
- 终端输入:
bash
mvn -v - 输出类似以下内容即为成功:
plaintext
Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08ccf28cc53) Maven home: D:\dev\apache-maven-3.9.6 Java version: 17.0.10, vendor: Eclipse Adoptium, runtime: C:\Program Files\Eclipse Adoptium\jdk-17.0.10+7 -
4. 配置 Maven 仓库(加速依赖下载)
默认 Maven 仓库在国外,建议配置阿里云镜像,并修改本地仓库路径(避免 C 盘占用)。
- 打开 Maven 安装目录下的
conf/settings.xml。 - 配置本地仓库路径:在
<settings>标签内添加(路径自定义):xml
<localRepository>D:/dev/maven-repo</localRepository> <!-- Windows --> <!-- 或 --> <localRepository>~/dev/maven-repo</localRepository> <!-- macOS/Linux --> - 配置阿里云镜像:在
<mirrors>标签内添加:xml
<mirror> <id>aliyunmaven</id> <mirrorOf>*</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> -
macOS/Linux:
- 编辑
~/.zshrc或~/.bash_profile,添加:bash
export MAVEN_HOME=~/dev/apache-maven-3.9.6 # 替换为实际路径 export PATH=$MAVEN_HOME/bin:$PATH - 生效配置:
source ~/.zshrc。 -
3. 配置环境变量
Windows:
- 新建系统变量
MAVEN_HOME,值为 Maven 解压路径(如D:\dev\apache-maven-3.9.6)。 - 编辑 Path,新增
%MAVEN_HOME%\bin。 -
2. 安装 Maven
- Windows:解压到自定义目录(如
D:\dev\apache-maven-3.9.6)。 - macOS/Linux:解压到
/usr/local/或~/dev/目录(如~/dev/apache-maven-3.9.6)。 -
二、Maven 安装与配置
Maven 是 Java 项目的构建工具,用于依赖管理和项目打包。
1. 下载 Maven
- 访问Maven 官网,下载最新版二进制压缩包(如
apache-maven-3.9.6-bin.zip)。 -
4. 验证 JDK 安装
- 打开终端 / 命令提示符,输入:
bash
java -version javac -version - 输出类似以下内容即为成功:
plaintext
openjdk version "17.0.10" 2024-01-16 LTS OpenJDK Runtime Environment Temurin-17.0.10+7 (build 17.0.10+7) OpenJDK 64-Bit Server VM Temurin-17.0.10+7 (build 17.0.10+7, mixed mode, sharing) -
macOS/Linux:
- 打开终端,编辑配置文件(
~/.bash_profile或~/.zshrc,根据 shell 类型选择):bash
vi ~/.zshrc # 或 .bash_profile - 添加以下内容(路径替换为实际 JDK 路径):
bash
export JAVA_HOME=/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home export PATH=$JAVA_HOME/bin:$PATH - 生效配置:
bash
source ~/.zshrc # 或 .bash_profile -
3. 配置环境变量(Windows 手动配置或 macOS)
Windows:
- 右键 “此电脑” → “属性” → “高级系统设置” → “环境变量”。
- 新建系统变量:
- 变量名:
JAVA_HOME - 变量值:JDK 安装路径(如
C:\Program Files\Eclipse Adoptium\jdk-17.0.10+7)。
- 变量名:
- 编辑系统变量 Path:
- 新增
%JAVA_HOME%\bin和%JAVA_HOME%\jre\bin(若存在 jre 目录)。
- 新增
-
macOS 系统:
- .pkg 安装包:双击文件 → 按照向导安装,默认路径为
/Library/Java/JavaVirtualMachines/temurin-17.jdk/Contents/Home。 - .tar.gz 压缩包:解压到
/Library/Java/JavaVirtualMachines/或自定义目录(如~/dev/jdk-17)。 -
2. 安装 JDK
Windows 系统:
- .msi 安装包:双击文件 → 勾选 “Add to PATH”(自动配置环境变量,推荐) → 选择安装路径(如
C:\Program Files\Eclipse Adoptium\jdk-17.0.10+7) → 点击 “Install” 完成。 - .zip 压缩包:解压到指定目录(如
D:\dev\jdk-17) → 手动配置环境变量(见步骤 3)。
② 快速搭建 SpringBoot 项目
方法二:使用 IDEA 内置工具(推荐,更便捷)
如果使用 IntelliJ IDEA(旗舰版,社区版需手动配置),可直接在 IDE 内生成项目,无需访问网页。
方法三:手动创建(了解底层,适合学习)
适合想深入理解项目结构的场景,手动配置 Maven/Gradle 文件。
项目启动与测试
总结
-
方法一:使用 Spring Initializr(官方推荐,最常用)
Spring 官方提供的初始化工具,可视化配置,适合快速生成基础项目结构。
-
访问官网打开 Spring Initializr(国内可访问 start.springboot.io 镜像)。
-
配置项目信息
- Project:选择构建工具(Maven/Gradle,推荐 Maven)。
- Language:选择开发语言(Java/Kotlin/Groovy,通常选 Java)。
- Spring Boot:选择版本(建议选 稳定版,如 3.2.x,避免最新快照版)。
- Project Metadata:填写 Group(组织 ID,如
com.example)、Artifact(项目名,如demo)、Package Name 等。 - Packaging:选择打包方式(Jar/War,Spring Boot 默认推荐 Jar,内置 Tomcat)。
- Java:选择 JDK 版本(需与本地安装的 JDK 匹配,如 JDK17)。
-
添加依赖(Dependencies)在搜索框中输入需要的依赖(如 Web、MySQL、MyBatis 等),勾选后自动添加到配置中。
- 基础 Web 项目必选:Spring Web(提供 RESTful 接口、内置服务器等)。
- 其他常用:Spring Data JPA、MyBatis、Lombok(简化代码)、Spring Security 等。
-
生成项目点击 Generate 按钮,下载压缩包,解压后导入 IDE(如 IDEA、Eclipse)即可。
-
新建项目打开 IDEA →
File → New → Project→ 左侧选择 Spring Initializr,默认使用官方地址(或替换为国内镜像)。 -
配置项目信息同方法一的步骤 2(Project Metadata、Java 版本等)。
-
选择依赖在依赖列表中勾选所需组件(如 Web、Lombok 等),IDEA 会实时显示选中的依赖。
-
完成创建选择项目保存路径,点击 Finish,IDEA 会自动下载依赖并构建项目。
-
创建目录结构按 Maven 标准结构创建文件夹:
plaintext
demo/ ├─ src/ │ ├─ main/ │ │ ├─ java/ │ │ │ └─ com/example/demo/ # 包路径 │ │ └─ resources/ # 配置文件 │ └─ test/ # 测试代码 └─ pom.xml # Maven配置文件 -
编写 pom.xml添加 Spring Boot 父工程和核心依赖(以 Maven 为例):
xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 父工程:统一管理依赖版本 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.0</version> <!-- 版本号 --> <relativePath/> </parent> <groupId>com.example</groupId> <artifactId>demo</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <java.version>17</java.version> <!-- JDK版本 --> </properties> <!-- 核心依赖:Web场景 --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 测试依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!-- 打包插件:支持Spring Boot的Jar包构建和运行 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> -
创建启动类在
src/main/java/com/example/demo/下新建启动类DemoApplication.java:java
运行
package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication // 核心注解:开启自动配置、组件扫描等 public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); // 启动Spring Boot } } -
验证项目运行
main方法,控制台输出Started DemoApplication in xxx seconds即表示成功。 -
启动项目
- IDE 中直接运行启动类的
main方法。 - 命令行:进入项目根目录,执行
mvn spring-boot:run(Maven)或./gradlew bootRun(Gradle)。
- IDE 中直接运行启动类的
-
测试接口(以 Web 项目为例)新建一个 Controller 类(如
HelloController.java):java
运行
package com.example.demo.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!"; } }重启项目后,访问
http://localhost:8080/hello,若返回字符串则说明搭建成功。 - 推荐使用 Spring Initializr 或 IDEA 内置工具,1-2 分钟即可完成基础项目搭建,重点是选对依赖和版本。
- 手动创建适合学习底层原理,理解 Spring Boot 的自动配置和依赖管理机制。
- 国内用户建议使用国内镜像(如
start.springboot.io)加速依赖下载。
③ 如何在SpringBoot中整合持久层框架(Mabatis、Mabatis-Plus、JPA等)
一、整合 MyBatis
MyBatis 是一款轻量级持久层框架,需要手动编写 SQL 和映射文件(或注解)。
1. 引入依赖
在pom.xml中添加 MyBatis 和数据库驱动依赖(以 MySQL 为例):
<!-- Spring Boot整合MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version> <!-- 版本需与Spring Boot兼容 -->
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 可选:数据库连接池(Spring Boot默认用HikariCP) -->
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</dependency>
2. 配置数据源
在application.yml(或application.properties)中配置数据库连接信息:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
username: root
password: 123456
hikari:
maximum-pool-size: 10 # 连接池最大连接数
# MyBatis配置(可选)
mybatis:
mapper-locations: classpath:mapper/*.xml # 映射文件路径(若用XML方式)
type-aliases-package: com.example.demo.entity # 实体类包路径(简化别名)
configuration:
map-underscore-to-camel-case: true # 开启下划线转驼峰(如user_name → userName)
3. 定义实体类(Entity)
public class User {
private Long id;
private String username;
private Integer age;
// 省略getter、setter、构造方法
}
4. 定义 Mapper 接口
两种方式:注解方式(简单 SQL)或XML 方式(复杂 SQL)。
-
注解方式(无需 XML):
@Mapper // 标记为MyBatis映射接口(或在启动类加@MapperScan("com.example.demo.mapper")批量扫描) public interface UserMapper { @Select("SELECT * FROM user WHERE id = #{id}") User getById(Long id); @Insert("INSERT INTO user(username, age) VALUES(#{username}, #{age})") @Options(useGeneratedKeys = true, keyProperty = "id") // 自增主键回显 int insert(User user); } -
XML 方式(推荐复杂 SQL):
- 创建
src/main/resources/mapper/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.demo.mapper.UserMapper"> <select id="getById" resultType="User"> SELECT * FROM user WHERE id = #{id} </select> <insert id="insert" useGeneratedKeys="true" keyProperty="id"> INSERT INTO user(username, age) VALUES(#{username}, #{age}) </insert> </mapper> - 对应的 Mapper 接口(无需注解):
public interface UserMapper { User getById(Long id); int insert(User user); }
- 创建
5. 测试使用
通过 Service 层调用 Mapper:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public User getUser(Long id) {
return userMapper.getById(id);
}
}
二、整合 MyBatis-Plus
MyBatis-Plus 是 MyBatis 的增强工具,提供 CRUD 通用接口、条件构造器等,简化开发。
1. 引入依赖
替换 MyBatis 依赖为 MyBatis-Plus:
<!-- MyBatis-Plus Starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version>
</dependency>
<!-- MySQL驱动(同上) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
2. 配置数据源
与 MyBatis 相同(application.yml),可额外添加 MyBatis-Plus 配置:
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.demo.entity
global-config:
db-config:
table-prefix: t_ # 表名前缀(如实体User对应表t_user)
id-type: auto # 主键自增策略
3. 定义实体类
使用@TableName(指定表名)、@TableId(主键)等注解:
@TableName("t_user") // 对应数据库表t_user
public class User {
@TableId(type = IdType.AUTO) // 主键自增
private Long id;
@TableField("username") // 对应表字段(若名称一致可省略)
private String username;
private Integer age;
// 省略getter、setter
}
4. 定义 Mapper 接口
继承BaseMapper<T>,无需手动编写基础 CRUD 方法:
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 继承后直接拥有selectById、insert、updateById、deleteById等方法
// 复杂SQL仍可通过注解或XML扩展
}
5. 测试使用
利用 MyBatis-Plus 的通用方法和条件构造器:
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 查询:根据ID
public User getById(Long id) {
return userMapper.selectById(id);
}
// 新增
public boolean add(User user) {
return userMapper.insert(user) > 0;
}
// 条件查询:年龄大于18的用户
public List<User> getByAge() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age", 18); // gt = greater than
return userMapper.selectList(queryWrapper);
}
}
三、整合 Spring Data JPA
JPA(Java Persistence API)是 ORM 规范,Spring Data JPA 基于 Hibernate 实现,提供全自动 CRUD 操作,适合快速开发。
1. 引入依赖
<!-- Spring Data JPA -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- MySQL驱动(同上) -->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
2. 配置数据源与 JPA
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test_db?useSSL=false&serverTimezone=UTC
username: root
password: 123456
jpa:
hibernate:
ddl-auto: update # 自动创建/更新表结构(create:每次启动重建,update:更新,none:不操作)
show-sql: true # 控制台打印SQL
properties:
hibernate:
format_sql: true # SQL格式化
database-platform: org.hibernate.dialect.MySQL8Dialect # 指定数据库方言
3. 定义实体类
使用 JPA 注解映射表关系:
@Entity // 标记为JPA实体
@Table(name = "t_user") // 对应表名
public class User {
@Id // 主键
@GeneratedValue(strategy = GenerationType.IDENTITY) // 自增策略
private Long id;
@Column(name = "username", length = 50) // 对应表字段
private String username;
private Integer age;
// 省略getter、setter
}
4. 定义 Repository 接口
继承JpaRepository<T, ID>,自动拥有 CRUD 方法:
// 泛型:实体类User,主键类型Long
public interface UserRepository extends JpaRepository<User, Long> {
// 支持方法名自动生成SQL(无需手动编写)
List<User> findByAgeGreaterThan(Integer age); // 等价于WHERE age > ?
User findByUsername(String username); // 等价于WHERE username = ?
}
5. 测试使用
通过 Service 调用 Repository:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 查询所有
public List<User> getAll() {
return userRepository.findAll();
}
// 根据年龄查询(自定义方法)
public List<User> getByAge(Integer age) {
return userRepository.findByAgeGreaterThan(age);
}
// 保存/更新(id存在则更新,否则新增)
public User save(User user) {
return userRepository.save(user);
}
}
总结
| 框架 | 特点 | 适用场景 |
|---|---|---|
| MyBatis | 轻量、SQL 可控性高,需手动编写映射 | 复杂 SQL 场景、性能要求高的系统 |
| MyBatis-Plus | 增强 MyBatis,提供通用 CRUD、条件构造器 | 简化开发,兼顾 SQL 灵活性 |
| JPA | 全自动 ORM,无需写 SQL,依赖方法名生成 | 快速开发、SQL 简单的业务(如后台管理系统) |
整合核心步骤:
- 引入对应框架的 Starter 依赖;
- 配置数据源(数据库连接信息);
- 定义实体类(映射数据库表);
- 定义数据访问接口(Mapper/Repository);
- 通过 Service 层调用接口实现数据库操作。
④ 如何进行数据缓存管理。
一、基础:使用 Spring Cache(注解驱动,简化缓存操作)
Spring Cache 提供了统一的缓存抽象,支持多种缓存实现(如内存缓存、Redis 等),通过注解即可完成缓存的增删改查。
1. 引入依赖
根据缓存类型选择依赖:
-
本地缓存(适合单节点应用,如 Caffeine):
xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <!-- Caffeine缓存(高性能本地缓存) --> <dependency> <groupId>com.github.ben-manes.caffeine</groupId> <artifactId>caffeine</artifactId> </dependency> -
分布式缓存(适合集群应用,如 Redis):
xml
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
2. 开启缓存支持
在启动类添加@EnableCaching注解:
java
运行
@SpringBootApplication
@EnableCaching // 开启缓存功能
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3. 配置缓存(以 Redis 为例)
在application.yml中配置缓存参数:
yaml
spring:
# Redis配置
redis:
host: localhost
port: 6379
password: 123456 # 无密码可省略
timeout: 5000ms
# 缓存配置
cache:
type: redis # 指定缓存类型为Redis(本地缓存可设为caffeine)
redis:
time-to-live: 3600000ms # 缓存过期时间(1小时)
key-prefix: "cache:" # 缓存key前缀
use-key-prefix: true # 启用前缀
cache-null-values: false # 是否缓存null值(防止缓存穿透)
本地缓存(Caffeine)配置:
yaml
spring:
cache:
type: caffeine
caffeine:
spec: maximumSize=1000,expireAfterWrite=60s # 最大1000条,写入后60秒过期
4. 核心缓存注解使用
通过注解在 Service 层控制缓存逻辑:
| 注解 | 作用 | 常用属性 |
|---|---|---|
@Cacheable | 方法执行前先查缓存,无则执行方法并缓存结果 | value/cacheNames(缓存名称)、key(缓存 key) |
@CachePut | 执行方法后更新缓存(不影响方法执行) | key(指定更新的缓存 key) |
@CacheEvict | 删除缓存 | allEntries=true(清空整个缓存) |
@Caching | 组合多个缓存操作(如同时更新 + 删除) | 包含cacheable、put、evict |
示例代码:
java
运行
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 查询:优先查缓存,无则查DB并缓存结果
@Cacheable(value = "userCache", key = "#id") // 缓存名称userCache,key为参数id
public User getById(Long id) {
System.out.println("查询DB:id=" + id); // 仅首次执行
return userMapper.selectById(id);
}
// 更新:执行后更新缓存(确保缓存与DB一致)
@CachePut(value = "userCache", key = "#user.id") // key为用户id
public User update(User user) {
userMapper.updateById(user);
return user; // 缓存此返回值
}
// 删除:删除对应缓存
@CacheEvict(value = "userCache", key = "#id")
public void delete(Long id) {
userMapper.deleteById(id);
}
// 清空整个缓存(如批量删除场景)
@CacheEvict(value = "userCache", allEntries = true)
public void deleteAll() {
// 批量删除逻辑
}
}
5. 自定义缓存 Key
默认 key 生成策略为方法名+参数,可通过keyGenerator自定义:
java
运行
@Configuration
public class CacheConfig {
@Bean
public KeyGenerator myKeyGenerator() {
return (target, method, params) -> {
// 生成格式:类名.方法名:参数1,参数2...
StringBuilder key = new StringBuilder();
key.append(target.getClass().getName()).append(".");
key.append(method.getName()).append(":");
for (Object param : params) {
key.append(param).append(",");
}
return key.toString();
};
}
}
使用自定义生成器:
java
运行
@Cacheable(value = "userCache", keyGenerator = "myKeyGenerator")
public User getByUsername(String username) { ... }
二、高级:分布式缓存(Redis)进阶配置
当应用部署在多节点(集群)时,本地缓存会导致数据不一致,需使用 Redis 等分布式缓存。
1. 序列化配置(解决 Redis 存储对象乱码)
默认 JDK 序列化会导致 Redis 中数据可读性差,建议改用 JSON 序列化:
java
运行
@Configuration
public class RedisCacheConfig {
@Bean
public RedisCacheConfiguration cacheConfiguration() {
// JSON序列化器
RedisSerializer<Object> serializer = new GenericJackson2JsonRedisSerializer();
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofHours(1)) // 全局过期时间
.serializeKeysWith(RedisSerializationContext.SerializationPair
.fromSerializer(new StringRedisSerializer())) // key用String序列化
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(serializer)) // value用JSON序列化
.disableCachingNullValues(); // 不缓存null
}
}
2. 缓存穿透、击穿、雪崩解决方案
-
缓存穿透:查询不存在的数据,导致每次都访问 DB。解决:缓存 null 值(
cache-null-values: true),或使用布隆过滤器提前拦截。 -
缓存击穿:热点 key 过期瞬间,大量请求穿透到 DB。解决:加互斥锁(如 Redisson 的
RLock),或设置热点 key 永不过期。 -
缓存雪崩:大量 key 同时过期,导致 DB 压力骤增。解决:过期时间加随机值(避免同时过期),或使用多级缓存(本地缓存 + Redis)。
示例:用互斥锁解决缓存击穿
java
运行
@Service
public class UserService {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private UserMapper userMapper;
public User getByIdWithLock(Long id) {
String key = "cache:user:" + id;
// 1. 查缓存
String json = redisTemplate.opsForValue().get(key);
if (json != null) {
return JSON.parseObject(json, User.class);
}
// 2. 缓存未命中,加锁
String lockKey = "lock:user:" + id;
boolean locked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 10, TimeUnit.SECONDS);
if (!locked) {
// 未抢到锁,重试
try {
Thread.sleep(100);
} catch (InterruptedException e) { ... }
return getByIdWithLock(id); // 递归重试
}
try {
// 3. 查DB
User user = userMapper.selectById(id);
if (user != null) {
// 4. 写入缓存
redisTemplate.opsForValue().set(key, JSON.toJSONString(user), 1, TimeUnit.HOURS);
}
return user;
} finally {
// 5. 释放锁
redisTemplate.delete(lockKey);
}
}
}
三、缓存管理最佳实践
- 缓存粒度:缓存高频访问、变化少的数据(如字典、用户信息),避免缓存大对象或频繁变化的数据。
- 过期策略:根据业务设置合理的 TTL(生存时间),避免缓存数据长期无效。
- 一致性:更新 DB 后需同步更新或删除缓存(
@CachePut/@CacheEvict),避免缓存与 DB 不一致。 - 监控:通过 Redis 监控工具(如 Redis Insight)监控缓存命中率、内存占用等指标。
总结
- 简单场景:用
@EnableCaching+@Cacheable等注解,配合 Redis 实现分布式缓存。 - 复杂场景:自定义序列化、解决缓存三大问题(穿透、击穿、雪崩),必要时引入 Redisson 等工具增强分布式锁能力。
- 核心目标:减少 DB 访问,同时保证缓存与数据一致性。
⑤ 如何使用Thymeleaf进行视图开发。
一、环境准备
1. 引入依赖
在 pom.xml 中添加 Thymeleaf 依赖(Spring Boot 会自动配置):
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2. 配置 Thymeleaf(可选)
默认配置已满足基本需求,如需自定义,在 application.yml 中配置:
yaml
spring:
thymeleaf:
prefix: classpath:/templates/ # 模板文件存放路径(默认)
suffix: .html # 模板文件后缀(默认)
mode: HTML5 # 模板模式
encoding: UTF-8 # 编码
cache: false # 开发环境关闭缓存(避免修改后需重启)
二、基础使用流程
1. 创建控制器(Controller)
通过控制器向前端传递数据:
java
运行
@Controller // 注意:用@Controller而非@RestController(@RestController返回JSON)
public class UserController {
// 向视图传递数据
@GetMapping("/user")
public String user(Model model) {
// 存储单个对象
User user = new User(1L, "张三", 20);
model.addAttribute("user", user);
// 存储集合
List<User> users = Arrays.asList(
new User(2L, "李四", 22),
new User(3L, "王五", 25)
);
model.addAttribute("users", users);
// 存储基本类型
model.addAttribute("message", "欢迎使用Thymeleaf!");
model.addAttribute("isVip", true);
// 返回模板文件名(对应 templates/user.html)
return "user";
}
}
2. 创建实体类(User)
java
运行
public class User {
private Long id;
private String name;
private Integer age;
// 构造方法、getter、setter
public User(Long id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
// getter和setter省略
}
3. 创建 Thymeleaf 模板
在 src/main/resources/templates/ 目录下创建 user.html:
html
预览
<!DOCTYPE html>
<!-- 声明 Thymeleaf 命名空间,支持IDE自动提示 -->
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户信息</title>
</head>
<body>
<!-- 1. 输出文本(th:text 替换标签内容) -->
<h1 th:text="${message}">默认文本(浏览器直接打开时显示)</h1>
<!-- 2. 访问对象属性(${对象.属性名}) -->
<div>
<p>ID:<span th:text="${user.id}">0</span></p>
<p>姓名:<span th:text="${user.name}">未知</span></p>
<p>年龄:<span th:text="${user.age}">0</span></p>
</div>
<!-- 3. 条件判断(th:if / th:unless) -->
<p th:if="${isVip}">您是VIP用户</p>
<p th:unless="${isVip}">您是普通用户</p>
<!-- 4. 循环遍历(th:each) -->
<h3>用户列表</h3>
<ul>
<!-- 遍历users集合,每次迭代的元素为u -->
<li th:each="u : ${users}">
<span th:text="${u.id}"></span> -
<span th:text="${u.name}"></span> -
<span th:text="${u.age}"></span>
</li>
</ul>
<!-- 5. 链接(th:href) -->
<a th:href="@{/home}">首页</a> <!-- 生成 /home 路径 -->
<a th:href="@{/user/detail(id=${user.id})}">用户详情</a> <!-- 生成 /user/detail?id=1 -->
<!-- 6. 内联文本([[ ]] 等价于 th:text,需在标签内使用) -->
<p>内联文本示例:[[${user.name}]]的年龄是[[${user.age}]]</p>
</body>
</html>
三、核心语法详解
1. 变量表达式(${...})
用于获取模型中的数据,支持对象、集合、基本类型:
- 访问对象属性:
${user.name}(调用user.getName()) - 访问集合元素:
${users[0].name} - 调用方法:
${user.getName()}(与user.name等价)
2. 选择表达式(*{...})
结合 th:object 使用,简化对象属性访问:
html
预览
<div th:object="${user}"> <!-- 声明当前对象为user -->
<p>姓名:<span th:text="*{name}"></span></p> <!-- 等价于 ${user.name} -->
<p>年龄:<span th:text="*{age}"></span></p>
</div>
3. 链接表达式(@{...})
生成 URL,自动处理上下文路径(Context Path):
- 绝对路径:
@{http://www.example.com} - 相对路径:
- 相对于当前页面:
@{user/detail}→/当前上下文/user/detail - 相对于根路径:
@{/user/detail}→/当前上下文/user/detail(推荐)
- 相对于当前页面:
- 带参数:
@{/user/detail(id=${user.id}, name=${user.name})}→/user/detail?id=1&name=张三
4. 条件判断
th:if:条件为true时显示标签th:unless:条件为false时显示标签(与th:if相反)th:switch+th:case:多条件判断
html
预览
<div th:switch="${user.age}">
<p th:case="20">年龄是20</p>
<p th:case="22">年龄是22</p>
<p th:case="*">其他年龄</p> <!-- * 表示默认 -->
</div>
5. 循环遍历(th:each)
遍历集合、数组、Map 等,支持获取迭代状态:
html
预览
<ul>
<!-- status 为迭代状态对象,包含 index(索引)、count(计数)、size(总长度)等 -->
<li th:each="u, status : ${users}">
索引:<span th:text="${status.index}"></span>,
计数:<span th:text="${status.count}"></span>,
姓名:<span th:text="${u.name}"></span>
</li>
</ul>
6. 模板复用(片段包含)
-
定义片段:用
th:fragment标记可复用的代码块(如header.html):html
预览
<!-- templates/header.html --> <header th:fragment="siteHeader(title)"> <h1 th:text="${title}">网站标题</h1> <nav>菜单导航</nav> </header> -
引入片段:用
th:include或th:replace引入(推荐th:replace):html
预览
<!-- 在 user.html 中引入 header 片段 --> <div th:replace="header :: siteHeader('用户页面')"></div> <!-- 语法:模板名 :: 片段名(参数) --> -
片段排除:用
th:remove移除不需要的标签(如开发时的占位符):html
预览
<p th:remove="all">此内容在渲染时会被移除</p>
7. 表单处理
结合 th:field 绑定表单数据到模型对象:
html
预览
<!-- 表单提交到 /user/save,方法为POST -->
<form th:action="@{/user/save}" th:method="post" th:object="${user}">
<!-- 绑定 user.id -->
<input type="hidden" th:field="*{id}">
<!-- 绑定 user.name,自动设置 name 和 value 属性 -->
<input type="text" th:field="*{name}" placeholder="姓名">
<!-- 绑定 user.age -->
<input type="number" th:field="*{age}" placeholder="年龄">
<button type="submit">提交</button>
</form>
控制器接收表单数据:
java
运行
@PostMapping("/user/save")
public String save(User user) { // 自动绑定表单数据到User对象
// 保存逻辑...
return "redirect:/user"; // 重定向到用户列表页
}
四、开发技巧
- 关闭缓存:开发时设置
spring.thymeleaf.cache=false,修改模板后无需重启应用。 - 自然模板:Thymeleaf 模板可直接在浏览器中打开(显示默认文本),便于前端调试。
- IDE 支持:IntelliJ IDEA 或 Eclipse 安装 Thymeleaf 插件,获得语法高亮和自动提示。
- 内置对象:Thymeleaf 提供常用内置对象,如:
#request:HttpServletRequest 对象#session:HttpSession 对象#dates:日期格式化工具(#dates.format(user.birthday, 'yyyy-MM-dd'))#strings:字符串工具(#strings.isEmpty(user.name))
总结
Thymeleaf 通过简洁的标签和表达式,实现了后端数据与前端视图的无缝整合,核心步骤为:
- 引入依赖并配置(简化版可省略配置);
- 控制器通过
Model传递数据; - 模板中使用
th:*标签渲染数据,支持条件、循环、表单等功能; - 利用片段复用减少重复代码。
⑥ 如何进行权限控制和安全控制。
一、核心概念
- 认证(Authentication):验证用户身份(如用户名密码登录、OAuth2 登录)。
- 授权(Authorization):控制用户能访问哪些资源(如接口、页面)。
- 角色(Role):一组权限的集合(如
ROLE_ADMIN、ROLE_USER)。 - 权限(Permission):具体操作权限(如
user:read、user:write)。
二、整合 Spring Security 实现权限控制
1. 引入依赖
在pom.xml中添加 Spring Security 依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- 如需操作数据库存储用户/权限,添加JDBC依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId> <!-- 或mybatis -->
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
2. 配置 Spring Security(核心)
创建配置类,继承WebSecurityConfigurerAdapter(Spring Security 5.7 + 推荐用组件式配置,这里以兼容方式示例):
java
运行
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启方法级权限控制
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 注入自定义用户服务(从数据库查询用户)
@Autowired
private UserDetailsService userDetailsService;
// 密码加密器(Spring Security 5+强制要求密码加密)
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // 推荐BCrypt加密
}
// 配置认证管理器(用户身份验证逻辑)
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 使用自定义用户服务+密码加密器
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
// 配置HTTP请求授权规则
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // 开发环境可关闭CSRF保护(生产环境需开启)
.authorizeRequests()
// 放行静态资源和登录页
.antMatchers("/login", "/css/**", "/js/**").permitAll()
// 管理员角色才能访问/admin/**
.antMatchers("/admin/**").hasRole("ADMIN")
// 需要user:read权限才能访问/user/**
.antMatchers("/user/**").hasAuthority("user:read")
// 其他所有请求需要认证(登录后才能访问)
.anyRequest().authenticated()
.and()
// 配置表单登录
.formLogin()
.loginPage("/login") // 自定义登录页路径
.defaultSuccessUrl("/index") // 登录成功后跳转页
.failureUrl("/login?error") // 登录失败后跳转页
.permitAll() // 允许所有用户访问登录页
.and()
// 配置退出登录
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login?logout") // 退出成功后跳转页
.permitAll();
}
}
3. 实现自定义用户服务(UserDetailsService)
从数据库查询用户信息(用户名、密码、角色、权限),并封装成UserDetails对象:
java
运行
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository; // 假设用JPA操作数据库
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 1. 从数据库查询用户
User user = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("用户不存在"));
// 2. 转换用户角色和权限为Spring Security需要的格式
// 角色需以"ROLE_"为前缀,权限直接使用字符串
Collection<? extends GrantedAuthority> authorities = user.getRoles().stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName())) // 角色
.collect(Collectors.toList());
// 额外添加权限(如从user.getPermissions()获取)
user.getPermissions().forEach(perm ->
authorities.add(new SimpleGrantedAuthority(perm.getName()))
);
// 3. 返回UserDetails对象(包含用户名、加密后的密码、权限集合等)
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(), // 数据库中存储的是加密后的密码
user.isEnabled(), // 账号是否启用
true, // 账号是否未过期
true, // 凭证是否未过期
true, // 账号是否未锁定
authorities
);
}
}
4. 数据库设计(用户 - 角色 - 权限关联)
典型的多对多关系设计:
users:用户表(id, username, password, enabled)roles:角色表(id, name, description)permissions:权限表(id, name, description)user_roles:用户 - 角色关联表(user_id, role_id)role_permissions:角色 - 权限关联表(role_id, permission_id)
示例实体类(JPA):
java
运行
// User实体
@Entity
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password; // 存储BCrypt加密后的密码
private boolean enabled = true;
// 多对多关联角色
@ManyToMany(fetch = FetchType.EAGER) // 立即加载角色
@JoinTable(
name = "user_roles",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
// 多对多关联权限(或通过角色关联,二选一)
@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(
name = "user_permissions",
joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "permission_id")
)
private Set<Permission> permissions = new HashSet<>();
// getter/setter
}
三、权限控制方式
1. URL 级别的权限控制(配置类中)
通过HttpSecurity的antMatchers()指定 URL 的访问权限,如:
java
运行
.antMatchers("/admin/**").hasRole("ADMIN") // 角色控制
.antMatchers("/user/**").hasAuthority("user:read") // 权限控制
.antMatchers("/public/**").permitAll() // 无需认证
.anyRequest().authenticated() // 其他需认证
2. 方法级别的权限控制(注解)
在 Service 或 Controller 方法上使用注解,需开启@EnableGlobalMethodSecurity(prePostEnabled = true):
| 注解 | 作用 | 示例 |
|---|---|---|
@PreAuthorize | 方法执行前检查权限 | @PreAuthorize("hasRole('ADMIN')") |
@PostAuthorize | 方法执行后检查权限(较少用) | @PostAuthorize("returnObject.username == authentication.name") |
@PreFilter | 过滤集合参数 | @PreFilter("filterObject.owner == authentication.name") |
@PostFilter | 过滤返回的集合 | @PostFilter("filterObject.owner == authentication.name") |
示例:
java
运行
@RestController
public class UserController {
// 只有ADMIN角色能访问
@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/users")
public List<User> getAllUsers() { ... }
// 需要user:write权限,且只能操作自己的资源
@PreAuthorize("hasAuthority('user:write') and #id == authentication.principal.id")
@PutMapping("/user/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) { ... }
}
3. 页面元素级别的权限控制(Thymeleaf)
结合 Thymeleaf 的 Spring Security 方言,控制页面元素是否显示:
- 引入依赖(Thymeleaf 与 Security 整合):
xml
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
- 在页面中使用:
html
预览
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<body>
<!-- 显示当前登录用户信息 -->
<div sec:authorize="isAuthenticated()">
用户名:<span sec:authentication="name"></span>
角色:<span sec:authentication="principal.authorities"></span>
</div>
<!-- 只有ADMIN角色可见 -->
<a href="/admin/users" sec:authorize="hasRole('ADMIN')">用户管理</a>
<!-- 有user:write权限可见 -->
<button sec:authorize="hasAuthority('user:write')">编辑用户</button>
<!-- 未登录时显示登录按钮 -->
<a href="/login" sec:authorize="isAnonymous()">登录</a>
<!-- 登录后显示退出按钮 -->
<a href="/logout" sec:authorize="isAuthenticated()">退出</a>
</body>
</html>
四、安全增强功能
1. 密码加密
使用BCryptPasswordEncoder加密密码(不可逆),存储加密后的字符串:
java
运行
// 加密示例(通常在用户注册时调用)
@Service
public class UserService {
@Autowired
private PasswordEncoder passwordEncoder;
public void createUser(String username, String rawPassword) {
String encodedPassword = passwordEncoder.encode(rawPassword); // 加密
// 保存到数据库(存储encodedPassword)
}
}
2. 防止暴力破解(限制登录失败次数)
使用UserDetailsChecker或第三方库(如spring-security-login-lock)实现:
java
运行
@Bean
public AuthenticationFailureHandler failureHandler() {
return new SimpleUrlAuthenticationFailureHandler("/login?error") {
@Override
public void onAuthenticationFailure(...) {
// 记录失败次数,超过阈值锁定账号
String username = exception.getAuthentication().getName();
userService.incrementLoginFailureCount(username);
super.onAuthenticationFailure(request, response, exception);
}
};
}
3. 集成 OAuth2/OpenID(第三方登录)
如需支持微信、GitHub 等第三方登录,引入 OAuth2 依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
配置第三方登录信息(application.yml):
yaml
spring:
security:
oauth2:
client:
registration:
github:
client-id: 你的GitHub客户端ID
client-secret: 你的GitHub客户端密钥
scope: read:user
4. CSRF 保护
生产环境需开启 CSRF 保护(默认开启),表单需携带 CSRF 令牌:
html
预览
<form th:action="@{/user/save}" method="post">
<!-- 自动生成CSRF令牌 -->
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
<!-- 其他表单字段 -->
</form>
五、总结
Spring Security 实现权限控制的核心步骤:
- 引入依赖并配置
SecurityConfig,定义 URL 访问规则、登录 / 退出行为。 - 实现
UserDetailsService,从数据库加载用户信息(用户名、密码、权限)。 - 通过URL 级别(配置类)或方法级别(注解)控制权限。
- 结合 Thymeleaf 实现页面元素的权限控制。
- 增强安全特性:密码加密、防暴力破解、CSRF 保护、第三方登录等。
⑦ 消息服务和任务管理。
一、消息服务(异步通信)
消息服务通过消息队列(如 RabbitMQ、Kafka、ActiveMQ)实现组件间的异步通信,解耦系统、削峰填谷。Spring Boot 通过Spring AMQP(RabbitMQ)、Spring Kafka等组件简化集成。
1. 整合 RabbitMQ(最常用)
RabbitMQ 是基于 AMQP 协议的消息队列,支持多种消息模式(简单队列、工作队列、扇形交换机、主题交换机等)。
步骤 1:安装 RabbitMQ
- 本地安装:RabbitMQ 官网 下载,启动后访问
http://localhost:15672(默认账号密码guest/guest)。 - 云服务:使用阿里云、AWS 等提供的 RabbitMQ 服务。
步骤 2:引入依赖
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
步骤 3:配置 RabbitMQ
在application.yml中配置连接信息:
yaml
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
virtual-host: / # 虚拟主机(默认/)
步骤 4:定义交换机、队列和绑定关系
通过配置类声明消息路由规则:
java
运行
@Configuration
public class RabbitConfig {
// 队列名
public static final String DEMO_QUEUE = "demo.queue";
// 交换机名
public static final String DEMO_EXCHANGE = "demo.exchange";
// 路由键
public static final String DEMO_ROUTING_KEY = "demo.routing.key";
// 声明队列
@Bean
public Queue demoQueue() {
// durable:是否持久化;exclusive:是否独占;autoDelete:无消费者时是否自动删除
return QueueBuilder.durable(DEMO_QUEUE).build();
}
// 声明交换机(主题交换机,支持通配符路由)
@Bean
public TopicExchange demoExchange() {
return ExchangeBuilder.topicExchange(DEMO_EXCHANGE).durable(true).build();
}
// 绑定队列到交换机(指定路由键)
@Bean
public Binding binding(Queue demoQueue, TopicExchange demoExchange) {
return BindingBuilder.bind(demoQueue).to(demoExchange).with(DEMO_ROUTING_KEY);
}
}
步骤 5:发送消息(生产者)
使用RabbitTemplate发送消息:
java
运行
@Service
public class MessageProducer {
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMessage(String content) {
// 发送字符串消息
rabbitTemplate.convertAndSend(
RabbitConfig.DEMO_EXCHANGE,
RabbitConfig.DEMO_ROUTING_KEY,
content
);
// 发送对象消息(需序列化,推荐用JSON)
User user = new User(1L, "张三");
rabbitTemplate.convertAndSend(
RabbitConfig.DEMO_EXCHANGE,
RabbitConfig.DEMO_ROUTING_KEY,
user
);
}
}
步骤 6:接收消息(消费者)
使用@RabbitListener注解监听队列:
java
运行
@Service
public class MessageConsumer {
// 监听指定队列
@RabbitListener(queues = RabbitConfig.DEMO_QUEUE)
public void receiveMessage(String content) {
System.out.println("收到字符串消息:" + content);
}
// 监听对象消息(需配置JSON反序列化)
@RabbitListener(queues = RabbitConfig.DEMO_QUEUE)
public void receiveUser(User user) {
System.out.println("收到用户消息:" + user.getName());
}
}
JSON 序列化配置(可选)
默认使用 JDK 序列化,建议改为 JSON:
java
运行
@Configuration
public class RabbitJsonConfig {
@Bean
public MessageConverter messageConverter() {
return new Jackson2JsonMessageConverter();
}
}
2. 整合 Kafka(高吞吐场景)
Kafka 适合大数据量、高吞吐的消息场景,整合方式类似 RabbitMQ:
- 引入依赖:
spring-boot-starter-kafka - 配置:
spring.kafka.bootstrap-servers=localhost:9092 - 发送:
KafkaTemplate.send(topic, message) - 接收:
@KafkaListener(topics = "topic-name")
二、任务管理
Spring Boot 支持两种任务:异步任务(非阻塞执行)和定时任务(按时间规则执行)。
1. 异步任务(@Async)
通过@Async注解标记方法为异步执行,避免阻塞主线程。
步骤 1:开启异步支持
在启动类或配置类添加@EnableAsync:
java
运行
@SpringBootApplication
@EnableAsync // 开启异步任务
public class DemoApplication { ... }
步骤 2:定义异步方法
在 Service 中用@Async标记方法:
java
运行
@Service
public class AsyncService {
// 异步执行此方法
@Async
public CompletableFuture<String> doAsyncTask() {
try {
Thread.sleep(3000); // 模拟耗时操作
} catch (InterruptedException e) { ... }
return CompletableFuture.completedFuture("异步任务完成");
}
}
步骤 3:调用异步方法
java
运行
@Controller
public class TaskController {
@Autowired
private AsyncService asyncService;
@GetMapping("/async")
public String testAsync() throws ExecutionException, InterruptedException {
// 调用异步方法(立即返回,不阻塞)
CompletableFuture<String> future = asyncService.doAsyncTask();
// 等待结果(可选)
String result = future.get();
System.out.println(result);
return "index";
}
}
自定义线程池(可选)
默认使用 SimpleAsyncTaskExecutor,建议自定义线程池优化性能:
java
运行
@Configuration
public class AsyncConfig {
@Bean(name = "asyncExecutor")
public Executor asyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(5); // 核心线程数
executor.setMaxPoolSize(10); // 最大线程数
executor.setQueueCapacity(25); // 队列容量
executor.setThreadNamePrefix("Async-"); // 线程名前缀
executor.initialize();
return executor;
}
}
指定线程池:@Async("asyncExecutor")
2. 定时任务(@Scheduled)
按时间规则自动执行任务,如定时备份数据、发送提醒。
步骤 1:开启定时任务支持
在启动类添加@EnableScheduling:
java
运行
@SpringBootApplication
@EnableScheduling // 开启定时任务
public class DemoApplication { ... }
步骤 2:定义定时任务
用@Scheduled标记方法,指定执行规则:
java
运行
@Service
public class ScheduledService {
// fixedRate:固定间隔(毫秒),从上一次开始执行时间计算
@Scheduled(fixedRate = 5000)
public void task1() {
System.out.println("每5秒执行一次(fixedRate):" + new Date());
}
// fixedDelay:固定延迟(毫秒),从上一次执行完成时间计算
@Scheduled(fixedDelay = 3000)
public void task2() {
System.out.println("每3秒执行一次(fixedDelay):" + new Date());
}
// cron表达式:更灵活的时间规则(秒 分 时 日 月 周)
@Scheduled(cron = "0 0 12 * * ?") // 每天12点执行
public void task3() {
System.out.println("每天12点执行:" + new Date());
}
}
Cron 表达式详解
格式:秒 分 时 日 月 周 [年](年可选)常用示例:
0 0 8 * * ?:每天 8 点执行0 0/30 9-17 * * ?:9 点到 17 点,每 30 分钟执行0 0 12 ? * SAT:每周六 12 点执行0 0 1 1 * ?:每月 1 日 1 点执行
定时任务线程池配置(可选)
默认单线程执行所有定时任务,任务间可能阻塞,建议配置线程池:
yaml
spring:
task:
scheduling:
pool:
size: 5 # 定时任务线程池大小
thread-name-prefix: Scheduled- # 线程名前缀
三、总结
| 组件 | 用途 | 核心技术 |
|---|---|---|
| 消息服务 | 系统解耦、异步通信、削峰填谷 | RabbitMQ(@RabbitListener)、Kafka |
| 异步任务 | 非阻塞执行耗时操作 | @Async + 线程池 |
| 定时任务 | 按时间规则自动执行任务 | @Scheduled + Cron 表达式 |
⑧ 完整的项目开发流程等。
一、项目启动阶段
1. 需求分析与规划
- 目标:明确项目核心功能、业务场景、用户群体及非功能需求(性能、安全性、可扩展性等)。
- 输出物:
- 需求文档(PRD,Product Requirement Document):详细描述功能点、交互逻辑、业务规则(如用户注册流程、订单状态流转)。
- 原型设计:用 Axure、墨刀等工具绘制页面原型,明确 UI/UX 交互。
- 技术可行性分析:评估现有技术栈能否满足需求(如高并发场景需考虑缓存、分布式架构)。
2. 技术选型与架构设计
- 技术栈确定:
- 后端:Spring Boot 版本(如 3.2.x)、JDK 版本(如 JDK17)、数据库(MySQL/PostgreSQL)、持久层框架(MyBatis-Plus/JPA)、缓存(Redis)、消息队列(RabbitMQ)等。
- 前端:Vue/React/Angular、UI 组件库(Element UI/Ant Design)、构建工具(Webpack/Vite)。
- 部署:Docker、Kubernetes、CI/CD 工具(Jenkins/GitHub Actions)。
- 架构设计:
- 整体架构:单体架构(中小项目)或微服务架构(大型项目,需考虑服务注册发现、网关等)。
- 模块划分:按业务领域拆分(如用户模块、订单模块、支付模块),明确模块间依赖关系。
- 数据库设计:ER 图设计、表结构定义(字段类型、索引、外键),遵循三范式(避免冗余)。
- 输出物:架构设计文档、数据库设计文档(DDL)、技术栈清单。
二、开发阶段
1. 项目初始化与环境搭建
- 版本控制:创建 Git 仓库(GitHub/GitLab),分支策略约定(如
main主分支、develop开发分支、feature/*功能分支)。 - 项目骨架搭建:
- 用 Spring Initializr 生成基础项目,引入核心依赖(Web、数据库、安全框架等)。
- 统一项目结构(按模块划分包路径):
plaintext
com.example.project ├─ config/ # 配置类(数据库、安全、缓存等) ├─ controller/ # 接口层(接收请求、返回响应) ├─ service/ # 业务逻辑层(接口+实现) │ ├─ impl/ ├─ mapper/ # 数据访问层(MyBatis接口或JPA Repository) ├─ entity/ # 实体类(数据库映射、DTO/VO) ├─ common/ # 公共组件(工具类、常量、异常处理) ├─ exception/ # 自定义异常 └─ ProjectApplication.java # 启动类
- 开发规范制定:
- 代码规范:遵循阿里巴巴 Java 开发手册(命名规则、注释要求、异常处理)。
- 接口规范:RESTful API 设计(URL 命名、HTTP 方法、状态码、响应格式统一)。
json
// 统一响应格式示例 { "code": 200, // 状态码(200成功、400参数错误、500服务器异常) "message": "成功", // 提示信息 "data": { ... } // 业务数据 } - 数据库规范:表名 / 字段名小写 + 下划线,主键自增策略,通用字段(
create_time、update_time)。
2. 功能开发(迭代式)
- 分工开发:按模块分配任务,开发者基于
feature分支开发具体功能。 - 核心开发流程:
- 接口设计:先定义 Controller 接口(如
/api/v1/users/{id}),明确入参(DTO)和出参(VO)。 - 业务实现:Service 层编写业务逻辑,调用 Mapper 层操作数据库,处理事务(
@Transactional)。 - 数据访问:通过 MyBatis-Plus/JPA 实现 CRUD,复杂 SQL 用 XML 或注解编写。
- 公共组件开发:
- 全局异常处理(
@ControllerAdvice):统一捕获并处理异常,返回标准响应。 - 拦截器 / 过滤器:处理登录验证、日志记录、接口限流等。
- 工具类:日期、加密、JSON 转换等通用功能。
- 全局异常处理(
- 接口设计:先定义 Controller 接口(如
- 代码提交:遵循 Conventional Commits 规范(如
feat: 新增用户注册功能、fix: 修复订单查询bug),提交前自查代码规范。
3. 单元测试与集成测试
- 单元测试:用 JUnit 5 + Mockito 测试 Service 层方法,覆盖核心业务逻辑(如订单创建、权限校验)。
java
运行
@SpringBootTest public class UserServiceTest { @MockBean private UserMapper userMapper; @Autowired private UserService userService; @Test public void testGetUserById() { // 模拟Mapper返回 User mockUser = new User(1L, "test"); when(userMapper.selectById(1L)).thenReturn(mockUser); // 测试Service方法 User user = userService.getById(1L); assertEquals("test", user.getName()); } } - 集成测试:用
@SpringBootTest+TestRestTemplate测试 Controller 接口,验证 HTTP 请求响应是否符合预期。 - 测试覆盖率:通过 JaCoCo 等工具监控测试覆盖率,核心模块建议≥80%。
三、测试阶段
1. 功能测试
- 测试人员根据 PRD 执行黑盒测试,验证功能是否符合需求(如用户登录、下单流程)。
- 输出测试用例和 Bug 清单,开发者修复后回归测试。
2. 非功能测试
- 性能测试:用 JMeter 测试接口响应时间、并发量(如 1000 用户同时下单),优化瓶颈(如慢查询、未命中缓存)。
- 安全测试:检查 SQL 注入、XSS 攻击、权限漏洞(如越权访问他人订单),通过 Spring Security 加固。
- 兼容性测试:前端页面在不同浏览器、设备上的展示效果。
3. 回归测试与验收
- 修复 Bug 后,全面回归测试确保功能正常,无新问题引入。
- 邀请产品或客户进行验收测试(UAT),确认满足业务需求。
四、部署与上线阶段
1. 环境准备
- 区分环境:开发环境(dev)、测试环境(test)、预生产环境(staging)、生产环境(prod)。
- 配置管理:用
application-{profile}.yml区分不同环境的配置(数据库地址、Redis 端口等),敏感信息(密码)通过配置中心(Nacos/Apollo)或环境变量注入。
2. 构建与打包
- 用 Maven/Gradle 打包:
mvn clean package -DskipTests,生成 Jar/War 包。 - 容器化:编写 Dockerfile,构建镜像并推送到镜像仓库(Harbor/Docker Hub)。
dockerfile
FROM openjdk:17-jdk-slim COPY target/project-0.0.1-SNAPSHOT.jar /app.jar ENTRYPOINT ["java", "-jar", "/app.jar", "--spring.profiles.active=prod"]
3. 部署上线
- 单机部署:直接运行 Jar 包(
java -jar app.jar)或通过 Docker 启动容器。 - 集群部署:用 Kubernetes 编排容器,实现自动扩缩容、滚动更新。
- CI/CD 自动化:通过 Jenkins 配置流水线,实现代码提交→自动构建→测试→部署全流程自动化。
4. 监控与运维
- 监控:集成 Spring Boot Actuator 暴露监控端点,结合 Prometheus + Grafana 监控系统指标(CPU、内存、接口 QPS)。
- 日志:用 Logback/Log4j2 记录日志,通过 ELK(Elasticsearch+Logstash+Kibana)收集分析日志,快速定位问题。
- 告警:配置关键指标告警(如接口错误率过高、服务器负载超标),通过邮件 / 钉钉通知运维人员。
五、项目维护阶段
- Bug 修复:线上出现问题时,紧急修复并发布补丁版本(hotfix)。
- 功能迭代:根据用户反馈和业务需求,规划新功能迭代,重复开发→测试→部署流程。
- 系统优化:定期 review 代码,优化性能(如 SQL 索引优化、缓存策略调整),重构冗余模块。
- 文档更新:同步更新 API 文档(用 Swagger)、部署文档、运维手册,确保团队信息一致。
总结
完整的项目开发流程是需求驱动、迭代推进、测试保障、运维兜底的闭环:
- 前期通过需求分析和架构设计明确方向;
- 开发阶段遵循规范,注重代码质量和测试覆盖;
- 上线前通过多轮测试验证功能和性能;
- 上线后通过监控和运维确保系统稳定运行,并持续迭代优化。

769

被折叠的 条评论
为什么被折叠?



