|
@@ -0,0 +1,596 @@
|
|
|
|
|
+# Spring Boot 2.2.13 → 2.7.18 升级指南
|
|
|
|
|
+
|
|
|
|
|
+> 本文档基于 `ylrz_his_scrm_java` 项目现状编写,目标版本:**Spring Boot 2.7.18**(2.x 末代 LTS,仍支持 Java 8)。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 一、升级概览
|
|
|
|
|
+
|
|
|
|
|
+### 1.1 当前 vs 目标
|
|
|
|
|
+
|
|
|
|
|
+| 项 | 当前 | 升级后(Boot 2.7.18 BOM 默认) |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| Spring Boot | 2.2.13.RELEASE | **2.7.18** |
|
|
|
|
|
+| Spring Framework | 5.2.x | **5.3.31** |
|
|
|
|
|
+| Spring Security | 5.2.15(手动覆盖) | **5.7.11**(随 BOM,可不再 pin) |
|
|
|
|
|
+| Java | 1.8 | 1.8(不变) |
|
|
|
|
|
+| Servlet API | javax.* | javax.*(**不涉及 Jakarta 迁移**) |
|
|
|
|
|
+
|
|
|
|
|
+### 1.2 项目规模(影响工作量)
|
|
|
|
|
+
|
|
|
|
|
+| 维度 | 数量 |
|
|
|
|
|
+|---|---|
|
|
|
|
|
+| Java 源文件 | ~8500 |
|
|
|
|
|
+| Maven 模块 | 36+ |
|
|
|
|
|
+| 可运行 Spring Boot 应用 | **28** |
|
|
|
|
|
+| `SecurityConfig`(需迁移) | **26** |
|
|
|
|
|
+| `SwaggerConfig`(Springfox) | **23** |
|
|
|
|
|
+| `HandlerInterceptorAdapter`(已废弃) | **37** |
|
|
|
|
|
+| 共享配置文件 | `fs-service/src/main/resources/application-common.yml` |
|
|
|
|
|
+
|
|
|
|
|
+### 1.3 预估工期
|
|
|
|
|
+
|
|
|
|
|
+| 阶段 | 内容 | 预估 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| 阶段 0 | 准备与分支 | 0.5 天 |
|
|
|
|
|
+| 阶段 1 | POM / 依赖 | 1–2 天 |
|
|
|
|
|
+| 阶段 2 | 全局运行时配置 | 0.5 天 |
|
|
|
|
|
+| 阶段 3 | Spring Security 迁移 | 3–5 天 |
|
|
|
|
|
+| 阶段 4 | Swagger 兼容 | 1–3 天 |
|
|
|
|
|
+| 阶段 5 | 编译修复 & 启动 | 2–3 天 |
|
|
|
|
|
+| 阶段 6 | 回归测试 | 1–2 周 |
|
|
|
|
|
+
|
|
|
|
|
+**合计:约 2–4 周**(1 人全职,视测试深度而定)。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 二、升级前准备(阶段 0)
|
|
|
|
|
+
|
|
|
|
|
+### 2.1 创建升级分支
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+git checkout -b feature/spring-boot-2.7.18
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 2.2 建立基线
|
|
|
|
|
+
|
|
|
|
|
+- 记录当前各核心模块能否正常 `mvn package`、能否启动。
|
|
|
|
|
+- 导出当前依赖树备查:
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+mvn dependency:tree -pl fs-admin -Dverbose > docs/upgrade-baseline-admin-deps.txt
|
|
|
|
|
+mvn dependency:tree -pl fs-user-app -Dverbose > docs/upgrade-baseline-user-app-deps.txt
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 2.3 确定升级范围
|
|
|
|
|
+
|
|
|
|
|
+建议**一次性升 BOM**,不要停留在 2.3/2.5 中间版本——你们从 2.2 直接到 2.7,中间破坏性变更(路径匹配、循环依赖、Security API)集中处理更高效。
|
|
|
|
|
+
|
|
|
|
|
+### 2.4 升级顺序建议
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+fs-common / fs-framework(基础)
|
|
|
|
|
+ ↓
|
|
|
|
|
+fs-service(业务核心)
|
|
|
|
|
+ ↓
|
|
|
|
|
+fs-admin / fs-user-app / fs-company(主入口)
|
|
|
|
|
+ ↓
|
|
|
|
|
+其余 API / 任务 / MQ 模块
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 三、依赖与 POM 升级(阶段 1)
|
|
|
|
|
+
|
|
|
|
|
+### 3.1 修改根 `pom.xml`
|
|
|
|
|
+
|
|
|
|
|
+#### 3.1.1 升级 Spring Boot BOM
|
|
|
|
|
+
|
|
|
|
|
+```xml
|
|
|
|
|
+<dependency>
|
|
|
|
|
+ <groupId>org.springframework.boot</groupId>
|
|
|
|
|
+ <artifactId>spring-boot-dependencies</artifactId>
|
|
|
|
|
+ <version>2.7.18</version>
|
|
|
|
|
+ <type>pom</type>
|
|
|
|
|
+ <scope>import</scope>
|
|
|
|
|
+</dependency>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### 3.1.2 新增/调整 properties(建议值)
|
|
|
|
|
+
|
|
|
|
|
+```xml
|
|
|
|
|
+<properties>
|
|
|
|
|
+ <!-- 核心 -->
|
|
|
|
|
+ <spring-boot.version>2.7.18</spring-boot.version>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- 第三方 starter(与 Boot 2.7 对齐) -->
|
|
|
|
|
+ <mybatis-spring-boot.version>2.3.2</mybatis-spring-boot.version>
|
|
|
|
|
+ <druid.version>1.2.23</druid.version>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Redisson:Boot 2.7 对应 spring-data-27 -->
|
|
|
|
|
+ <redisson.version>3.27.2</redisson.version>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- MyBatis-Plus:当前 3.1.0 过旧,建议升级 -->
|
|
|
|
|
+ <mybatis-plus.version>3.5.5</mybatis-plus.version>
|
|
|
|
|
+</properties>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### 3.1.3 移除或下调的手动覆盖
|
|
|
|
|
+
|
|
|
|
|
+升级到 2.7.18 后,以下覆盖**可先删除**,改由 BOM 管理;删除后跑 `dependency:tree` 确认无 CVE 回退:
|
|
|
|
|
+
|
|
|
|
|
+| 属性 / 依赖 | 当前 | 建议 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `spring-security.version` 及 core/web/config 三件套 | 5.2.15 手动 pin | **删除**,使用 BOM 5.7.x |
|
|
|
|
|
+| `jackson.version` / `jackson-bom` | 2.12.7 手动 pin | **删除或改为仅覆盖个别 artifact** |
|
|
|
|
|
+| `logback.version` | 1.2.13 | Boot 2.7 自带 1.2.12+,可删除 |
|
|
|
|
|
+| `snakeyaml.version` | 1.33 | Boot 2.7 自带 1.30+,可删除 |
|
|
|
|
|
+
|
|
|
|
|
+**保留**(仍可能有传递依赖冲突):
|
|
|
|
|
+
|
|
|
|
|
+- `netty.version`、`hutool.version`、`okhttp.version`、`fastjson.version` 等安全相关 pin
|
|
|
|
|
+- `pagehelper`(你们有 SQL 注入 CVE 注释,需验证 BOM 版本是否 ≥ 5.3.1)
|
|
|
|
|
+
|
|
|
|
|
+#### 3.1.4 Redisson 适配(必改)
|
|
|
|
|
+
|
|
|
|
|
+根 `pom.xml` 与 `fs-service/pom.xml` 中:
|
|
|
|
|
+
|
|
|
|
|
+```xml
|
|
|
|
|
+<!-- 改前 -->
|
|
|
|
|
+<artifactId>redisson-spring-data-22</artifactId>
|
|
|
|
|
+
|
|
|
|
|
+<!-- 改后 -->
|
|
|
|
|
+<artifactId>redisson-spring-data-27</artifactId>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+`fs-service/pom.xml` 中排除 `redisson-spring-data-32` 的注释也需同步更新。
|
|
|
|
|
+
|
|
|
|
|
+#### 3.1.5 统一 spring-boot-maven-plugin
|
|
|
|
|
+
|
|
|
|
|
+当前各可运行模块 pin 了 **2.1.1.RELEASE**(如 `fs-admin/pom.xml`),建议:
|
|
|
|
|
+
|
|
|
|
|
+**方案 A(推荐)**:在根 `pom.xml` 的 `pluginManagement` 中统一管理:
|
|
|
|
|
+
|
|
|
|
|
+```xml
|
|
|
|
|
+<pluginManagement>
|
|
|
|
|
+ <plugins>
|
|
|
|
|
+ <plugin>
|
|
|
|
|
+ <groupId>org.springframework.boot</groupId>
|
|
|
|
|
+ <artifactId>spring-boot-maven-plugin</artifactId>
|
|
|
|
|
+ <version>${spring-boot.version}</version>
|
|
|
|
|
+ </plugin>
|
|
|
|
|
+ </plugins>
|
|
|
|
|
+</pluginManagement>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+子模块删除 `<version>2.1.1.RELEASE</version>`。
|
|
|
|
|
+
|
|
|
|
|
+**涉及模块(27 个)**:fs-admin、fs-user-app、fs-company、fs-company-app、fs-doctor-app、fs-store、fs-qw-*、fs-live-*、fs-ad-*、fs-wx-api、fs-watch、fs-redis、fs-websocket、fs-ai-chat、fs-common-api、fs-repeat-api、fs-ipad-task、fs-qwhook* 等。
|
|
|
|
|
+
|
|
|
|
|
+### 3.2 修改 `fs-common/pom.xml`
|
|
|
|
|
+
|
|
|
|
|
+#### 3.2.1 MyBatis-Plus
|
|
|
|
|
+
|
|
|
|
|
+```xml
|
|
|
|
|
+<!-- 改前 -->
|
|
|
|
|
+<artifactId>mybatis-plus-boot-starter</artifactId>
|
|
|
|
|
+<version>3.1.0</version>
|
|
|
|
|
+
|
|
|
|
|
+<!-- 改后 -->
|
|
|
|
|
+<artifactId>mybatis-plus-boot-starter</artifactId>
|
|
|
|
|
+<version>${mybatis-plus.version}</version> <!-- 3.5.5 -->
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### 3.2.2 spring-expression 版本冲突(重要)
|
|
|
|
|
+
|
|
|
|
|
+当前 `fs-common/pom.xml` 显式依赖了 **spring-expression 6.2.0**(Spring 6),与 Boot 2.7 的 Spring 5.3 **不兼容**。
|
|
|
|
|
+
|
|
|
|
|
+```xml
|
|
|
|
|
+<!-- 建议:删除该依赖,或改为不指定 version,由 BOM 管理 -->
|
|
|
|
|
+<dependency>
|
|
|
|
|
+ <groupId>org.springframework</groupId>
|
|
|
|
|
+ <artifactId>spring-expression</artifactId>
|
|
|
|
|
+ <!-- 删除 <version>6.2.0</version> -->
|
|
|
|
|
+</dependency>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 3.3 MySQL 驱动(可选)
|
|
|
|
|
+
|
|
|
|
|
+Boot 2.7 仍支持 `mysql-connector-java`,但官方已迁移到 `com.mysql:mysql-connector-j`。短期可不改;长期建议替换:
|
|
|
|
|
+
|
|
|
|
|
+```xml
|
|
|
|
|
+<dependency>
|
|
|
|
|
+ <groupId>com.mysql</groupId>
|
|
|
|
|
+ <artifactId>mysql-connector-j</artifactId>
|
|
|
|
|
+</dependency>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 3.4 验证命令
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+# 全量编译(先不要求启动)
|
|
|
|
|
+mvn clean compile -DskipTests
|
|
|
|
|
+
|
|
|
|
|
+# 检查冲突
|
|
|
|
|
+mvn dependency:tree -pl fs-admin | findstr /i "spring-security spring-framework spring-expression"
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 四、全局运行时配置(阶段 2)
|
|
|
|
|
+
|
|
|
|
|
+在 `fs-service/src/main/resources/application-common.yml` 的 `spring:` 节点下增加:
|
|
|
|
|
+
|
|
|
|
|
+```yaml
|
|
|
|
|
+spring:
|
|
|
|
|
+ # Boot 2.6+ 默认禁止循环依赖,老项目常见此问题
|
|
|
|
|
+ main:
|
|
|
|
|
+ allow-circular-references: true # 临时方案;启动稳定后逐步改为 false 并重构
|
|
|
|
|
+
|
|
|
|
|
+ # Boot 2.6+ 默认 PathPatternParser,与 Springfox 2.9.2 / 部分 antMatchers 不兼容
|
|
|
|
|
+ mvc:
|
|
|
|
|
+ pathmatch:
|
|
|
|
|
+ matching-strategy: ant_path_matcher # 短期保留 Springfox 时使用
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+> **说明**:`ant_path_matcher` 在 2.7 仍可用但已标记为过渡方案。若后续迁移到 springdoc-openapi,可移除此配置。
|
|
|
|
|
+
|
|
|
|
|
+### 4.1 Tomcat 配置项更名(如遇警告)
|
|
|
|
|
+
|
|
|
|
|
+Boot 2.4+ 部分 `server.tomcat.*` 属性已更名,你们当前使用:
|
|
|
|
|
+
|
|
|
|
|
+```yaml
|
|
|
|
|
+server:
|
|
|
|
|
+ tomcat:
|
|
|
|
|
+ max-threads: 800 # 建议改为 max-threads 或 threads.max
|
|
|
|
|
+ min-spare-threads: 30 # 建议改为 threads.min-spare
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+启动时若出现 deprecated 警告,按 Boot 2.7 文档调整即可,不影响功能。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 五、Spring Security 迁移(阶段 3,工作量最大)
|
|
|
|
|
+
|
|
|
|
|
+### 5.1 背景
|
|
|
|
|
+
|
|
|
|
|
+- Boot 2.7 自带 **Spring Security 5.7.x**
|
|
|
|
|
+- `WebSecurityConfigurerAdapter` 已在 5.7 **移除**
|
|
|
|
|
+- 项目共 **26 个** `SecurityConfig` 需迁移
|
|
|
|
|
+
|
|
|
|
|
+### 5.2 配置文件分类
|
|
|
|
|
+
|
|
|
|
|
+#### A 类:全放行 + StrictHttpFirewall(17 个,改动模式相同)
|
|
|
|
|
+
|
|
|
|
|
+适用模块:fs-user-app、fs-doctor-app、fs-live-app、fs-live-mq、fs-watch、fs-redis、fs-wx-api、fs-ad-api、fs-ad-new-api、fs-common-api、fs-repeat-api、fs-qwhook、fs-qwhook-msg、fs-qwhook-sop、fs-qw-mq、fs-qw-voice、fs-user-app-ai-chat、fs-company-app
|
|
|
|
|
+
|
|
|
|
|
+参考现有代码:`fs-user-app/.../SecurityConfig.java`
|
|
|
|
|
+
|
|
|
|
|
+#### B 类:JWT 完整鉴权(7 个,规则较多)
|
|
|
|
|
+
|
|
|
|
|
+| 模块 | 文件 | 特殊点 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| fs-framework | `fs-framework/.../SecurityConfig.java` | **fs-admin 依赖此模块**,规则最全 |
|
|
|
|
|
+| fs-company | `fs-company/.../SecurityConfig.java` | 使用 `MD5PasswordEncoder` |
|
|
|
|
|
+| fs-store | `fs-store/.../SecurityConfig.java` | 使用 `MD5PasswordEncoder` |
|
|
|
|
|
+| fs-qw-api | `fs-qw-api/.../SecurityConfig.java` | JWT + 白名单 |
|
|
|
|
|
+| fs-qw-api-msg | `fs-qw-api-msg/.../SecurityConfig.java` | JWT + 白名单 |
|
|
|
|
|
+| fs-qw-company-api | `fs-qw-company-api/.../SecurityConfig.java` | JWT + 白名单 |
|
|
|
|
|
+| fs-qw-task | `fs-qw-task/.../SecurityConfig.java` | JWT + 白名单 |
|
|
|
|
|
+| fs-ipad-task | `fs-ipad-task/.../SecurityConfig.java` | JWT + 白名单 |
|
|
|
|
|
+
|
|
|
|
|
+> **fs-admin** 无独立 SecurityConfig,通过 `fs-framework` 生效。
|
|
|
|
|
+
|
|
|
|
|
+### 5.3 推荐重构策略(减少重复劳动)
|
|
|
|
|
+
|
|
|
|
|
+**不要 26 个文件各改一遍。** 建议:
|
|
|
|
|
+
|
|
|
|
|
+1. 在 `fs-framework` 新增 2 个基类/工具:
|
|
|
|
|
+ - `PermitAllSecurityConfiguration`(A 类)
|
|
|
|
|
+ - `JwtSecurityConfigurationSupport`(B 类,抽取 filter 链构建)
|
|
|
|
|
+2. 各模块 `SecurityConfig` 改为 `@Import` 或 `@Configuration` + `@Bean SecurityFilterChain`
|
|
|
|
|
+3. 模块级差异(白名单 URL)通过 `@ConfigurationProperties` 或子类 override 注入
|
|
|
|
|
+
|
|
|
|
|
+### 5.4 迁移模板
|
|
|
|
|
+
|
|
|
|
|
+#### A 类:全放行(替代 `fs-user-app` 现有写法)
|
|
|
|
|
+
|
|
|
|
|
+```java
|
|
|
|
|
+@Configuration
|
|
|
|
|
+@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
|
|
|
|
+public class SecurityConfig {
|
|
|
|
|
+
|
|
|
|
|
+ @Bean
|
|
|
|
|
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
|
|
|
+ http
|
|
|
|
|
+ .csrf(csrf -> csrf.disable())
|
|
|
|
|
+ .authorizeHttpRequests(auth -> auth
|
|
|
|
|
+ .anyRequest().permitAll()
|
|
|
|
|
+ );
|
|
|
|
|
+ return http.build();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Bean
|
|
|
|
|
+ public AuthenticationManager authenticationManager(
|
|
|
|
|
+ AuthenticationConfiguration configuration) throws Exception {
|
|
|
|
|
+ return configuration.getAuthenticationManager();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Bean
|
|
|
|
|
+ public StrictHttpFirewall httpFirewall() {
|
|
|
|
|
+ StrictHttpFirewall firewall = new StrictHttpFirewall();
|
|
|
|
|
+ firewall.setAllowUrlEncodedDoubleSlash(true);
|
|
|
|
|
+ return firewall;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### B 类:JWT 鉴权(替代 `fs-framework` 现有写法)
|
|
|
|
|
+
|
|
|
|
|
+```java
|
|
|
|
|
+@Configuration
|
|
|
|
|
+@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
|
|
|
|
+public class SecurityConfig {
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired private UserDetailsService userDetailsService;
|
|
|
|
|
+ @Autowired private AuthenticationEntryPointImpl unauthorizedHandler;
|
|
|
|
|
+ @Autowired private LogoutSuccessHandlerImpl logoutSuccessHandler;
|
|
|
|
|
+ @Autowired private JwtAuthenticationTokenFilter authenticationTokenFilter;
|
|
|
|
|
+ @Autowired private CorsFilter corsFilter;
|
|
|
|
|
+
|
|
|
|
|
+ @Bean
|
|
|
|
|
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
|
|
|
+ http
|
|
|
|
|
+ .csrf(csrf -> csrf.disable())
|
|
|
|
|
+ .exceptionHandling(ex -> ex.authenticationEntryPoint(unauthorizedHandler))
|
|
|
|
|
+ .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
|
|
|
|
+ .authorizeHttpRequests(auth -> auth
|
|
|
|
|
+ .requestMatchers("/login", "/register", "/captchaImage").anonymous()
|
|
|
|
|
+ .requestMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
|
|
|
|
|
+ // ... 保留原有全部 antMatchers 路径 ...
|
|
|
|
|
+ .anyRequest().authenticated()
|
|
|
|
|
+ )
|
|
|
|
|
+ .headers(headers -> headers.frameOptions(frame -> frame.disable()))
|
|
|
|
|
+ .logout(logout -> logout
|
|
|
|
|
+ .logoutUrl("/logout")
|
|
|
|
|
+ .logoutSuccessHandler(logoutSuccessHandler)
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ http.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
|
|
|
|
|
+ http.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
|
|
|
|
|
+ http.addFilterBefore(corsFilter, LogoutFilter.class);
|
|
|
|
|
+
|
|
|
|
|
+ return http.build();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Bean
|
|
|
|
|
+ public AuthenticationManager authenticationManager(
|
|
|
|
|
+ AuthenticationConfiguration configuration) throws Exception {
|
|
|
|
|
+ return configuration.getAuthenticationManager();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Bean
|
|
|
|
|
+ public BCryptPasswordEncoder bCryptPasswordEncoder() {
|
|
|
|
|
+ return new BCryptPasswordEncoder();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
|
|
|
|
+ auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+#### API 对照表
|
|
|
|
|
+
|
|
|
|
|
+| 旧 API(5.2 / WebSecurityConfigurerAdapter) | 新 API(5.7 / SecurityFilterChain) |
|
|
|
|
|
+|---|---|
|
|
|
|
|
+| `extends WebSecurityConfigurerAdapter` | `@Bean SecurityFilterChain` |
|
|
|
|
|
+| `@EnableGlobalMethodSecurity` | `@EnableMethodSecurity` |
|
|
|
|
|
+| `configure(HttpSecurity http)` | `securityFilterChain(HttpSecurity http)` |
|
|
|
|
|
+| `authorizeRequests()` | `authorizeHttpRequests()` |
|
|
|
|
|
+| `antMatchers(...)` | `requestMatchers(...)` |
|
|
|
|
|
+| `authenticationManagerBean()` | `AuthenticationConfiguration.getAuthenticationManager()` |
|
|
|
|
|
+| `.csrf().disable()` | `.csrf(csrf -> csrf.disable())` |
|
|
|
|
|
+
|
|
|
|
|
+### 5.5 处理 fs-common 中的 Security 补丁
|
|
|
|
|
+
|
|
|
|
|
+升级后 Spring Security 升至 5.7.x,需重新评估以下类:
|
|
|
|
|
+
|
|
|
|
|
+| 文件 | 用途 | 建议 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `EagerSecurityHeadersBeanPostProcessor` | CVE-2026-22732 缓解 | 5.7 有官方修复,**验证后可删除** |
|
|
|
|
|
+| `TimingSafeAuthenticationManagerBeanPostProcessor` | CVE-2026-22746 缓解 | 5.7.23+ 有修复;先保留,官方版本覆盖后删除 |
|
|
|
|
|
+| `TimingSafeDaoAuthenticationProvider` | 同上 | 同上 |
|
|
|
|
|
+| `org.springframework.security.*` 包下自研类 | 覆盖框架类 | 升级后重点回归登录接口 |
|
|
|
|
|
+
|
|
|
|
|
+**注意**:不要同时保留自研 `TimingSafeDaoAuthenticationProvider` 与官方修复版行为,避免双重逻辑。
|
|
|
|
|
+
|
|
|
|
|
+### 5.6 Security 迁移检查清单
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 26 个 `SecurityConfig` 编译通过
|
|
|
|
|
+- [ ] fs-admin 登录 / 登出 / JWT 刷新
|
|
|
|
|
+- [ ] fs-user-app 接口鉴权(当前全 permitAll,确认是否符合预期)
|
|
|
|
|
+- [ ] fs-company / fs-store 的 MD5 密码编码仍生效
|
|
|
|
|
+- [ ] 各模块 Swagger 白名单路径仍可匿名访问
|
|
|
|
|
+- [ ] `@PreAuthorize` / `@Secured` 注解权限仍生效
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 六、Swagger / Springfox 兼容(阶段 4)
|
|
|
|
|
+
|
|
|
|
|
+### 6.1 现状
|
|
|
|
|
+
|
|
|
|
|
+- 使用 **Springfox 2.9.2**(`swagger.version`)
|
|
|
|
|
+- **23 个** `SwaggerConfig` + 多个 `ResourcesConfig` 注册 Swagger 静态资源
|
|
|
|
|
+- 共享配置 `application-common.yml` 中 `swagger.enabled: false`(生产默认关闭)
|
|
|
|
|
+
|
|
|
|
|
+### 6.2 短期方案(推荐先做,保证升级后能启动)
|
|
|
|
|
+
|
|
|
|
|
+1. 阶段 2 已配置 `spring.mvc.pathmatch.matching-strategy: ant_path_matcher`
|
|
|
|
|
+2. 保持 Springfox 2.9.2 不变
|
|
|
|
|
+3. 启动后访问 `/swagger-ui.html` 验证
|
|
|
|
|
+
|
|
|
|
|
+**已知风险**:Springfox 已停止维护,与 Boot 2.7 是「勉强兼容」,不是长期方案。
|
|
|
|
|
+
|
|
|
|
|
+### 6.3 长期方案(可选,单独排期)
|
|
|
|
|
+
|
|
|
|
|
+迁移到 **springdoc-openapi 1.7.x**(支持 Boot 2.7 + Java 8):
|
|
|
|
|
+
|
|
|
|
|
+```xml
|
|
|
|
|
+<dependency>
|
|
|
|
|
+ <groupId>org.springdoc</groupId>
|
|
|
|
|
+ <artifactId>springdoc-openapi-ui</artifactId>
|
|
|
|
|
+ <version>1.7.0</version>
|
|
|
|
|
+</dependency>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+- 删除 Springfox 依赖
|
|
|
|
|
+- 23 个 `SwaggerConfig` 合并为 1 个公共配置或删除(springdoc 自动扫描)
|
|
|
|
|
+- Controller 上 `@Api` → `@Tag`,`@ApiOperation` → `@Operation`(可渐进)
|
|
|
|
|
+
|
|
|
|
|
+### 6.4 SwaggerConfig 文件清单
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+fs-admin/src/main/java/com/fs/web/core/config/SwaggerConfig.java
|
|
|
|
|
+fs-user-app/.../SwaggerConfig.java
|
|
|
|
|
+fs-company-app/.../core/config/SwaggerConfig.java
|
|
|
|
|
+fs-doctor-app、fs-live-app、fs-live-mq、fs-watch、fs-redis、
|
|
|
|
|
+fs-wx-api、fs-ad-api、fs-common-api、fs-repeat-api、
|
|
|
|
|
+fs-qw-api、fs-qw-api-msg、fs-qw-company-api、fs-qw-task、
|
|
|
|
|
+fs-qw-mq、fs-qw-voice、fs-ipad-task、
|
|
|
|
|
+fs-qwhook、fs-qwhook-msg、fs-qwhook-sop、
|
|
|
|
|
+fs-user-app-ai-chat
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 七、其他代码调整(阶段 5)
|
|
|
|
|
+
|
|
|
|
|
+### 7.1 HandlerInterceptorAdapter(37 处,低优先级)
|
|
|
|
|
+
|
|
|
|
|
+多个模块的 `RepeatSubmitInterceptor`、`AuthorizationInterceptor` 继承了 `HandlerInterceptorAdapter`。
|
|
|
|
|
+
|
|
|
|
|
+- Boot 2.7 下**仍可编译运行**(deprecated)
|
|
|
|
|
+- 建议后续改为直接实现 `HandlerInterceptor` 接口,删除 `extends HandlerInterceptorAdapter`
|
|
|
|
|
+
|
|
|
|
|
+### 7.2 MyBatis / MyBatis-Plus
|
|
|
|
|
+
|
|
|
|
|
+- 升级 MyBatis-Plus 3.1.0 → 3.5.5 后,关注:
|
|
|
|
|
+ - `fieldStrategy: NOT_EMPTY` 等全局配置是否仍兼容(3.5 部分枚举有变更)
|
|
|
|
|
+ - 分页插件、乐观锁、多租户等自定义配置
|
|
|
|
|
+- 23 个 `MyBatisConfig.java` 若仅做别名扫描,一般无需改动
|
|
|
|
|
+
|
|
|
|
|
+### 7.3 业务代码
|
|
|
|
|
+
|
|
|
|
|
+- **无需 Jakarta 包名替换**(`javax.servlet` 等保持不变)
|
|
|
|
|
+- `fs-service` 等业务 Service / Controller **预计改动极少**
|
|
|
|
|
+- 重点回归:支付、订单、企微回调、直播、课程观看、Redis 锁
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 八、分模块启动验证(阶段 5–6)
|
|
|
|
|
+
|
|
|
|
|
+### 8.1 启动顺序
|
|
|
|
|
+
|
|
|
|
|
+| 优先级 | 模块 | 验证重点 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| P0 | fs-admin | 后台登录、菜单权限、Swagger |
|
|
|
|
|
+| P0 | fs-user-app | C 端 API、微信支付、订单 |
|
|
|
|
|
+| P0 | fs-company | 企业端 JWT、CRM |
|
|
|
|
|
+| P1 | fs-qw-api / fs-qw-task | 企微回调、定时任务 |
|
|
|
|
|
+| P1 | fs-live-app / fs-live-mq | 直播、MQ 消费 |
|
|
|
|
|
+| P2 | fs-qwhook* / fs-wx-api / fs-ad-* | 回调、广告 |
|
|
|
|
|
+| P2 | 其余模块 | 能启动、核心接口 200 |
|
|
|
|
|
+
|
|
|
|
|
+### 8.2 单模块启动示例
|
|
|
|
|
+
|
|
|
|
|
+```bash
|
|
|
|
|
+cd fs-admin
|
|
|
|
|
+mvn spring-boot:run -Dspring-boot.run.profiles=dev
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+### 8.3 常见问题排查
|
|
|
|
|
+
|
|
|
|
|
+| 现象 | 可能原因 | 处理 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| 启动报循环依赖 | Boot 2.6+ 默认禁止 | `allow-circular-references: true` |
|
|
|
|
|
+| Swagger 404 / 空文档 | PathPattern 不兼容 | `ant_path_matcher` |
|
|
|
|
|
+| 403 增多 | Security 规则迁移遗漏 | 对比旧 `antMatchers` 列表 |
|
|
|
|
|
+| Redisson 启动失败 | spring-data 版本不匹配 | 改用 `redisson-spring-data-27` |
|
|
|
|
|
+| `NoClassDefFoundError: spring-expression` | fs-common pin 了 Spring 6 | 删除 version 6.2.0 |
|
|
|
|
|
+| 静态资源 404 | ResourcesConfig 路径匹配变化 | 检查 `ResourcesConfig` |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 九、回归测试清单(阶段 6)
|
|
|
|
|
+
|
|
|
|
|
+### 9.1 基础设施
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 多数据源 / Druid 连接池正常
|
|
|
|
|
+- [ ] Redis / Redisson 分布式锁
|
|
|
|
|
+- [ ] MyBatis / MyBatis-Plus CRUD、分页
|
|
|
|
|
+- [ ] 定时任务(fs-quartz)
|
|
|
|
|
+- [ ] WebSocket(fs-websocket)
|
|
|
|
|
+
|
|
|
|
|
+### 9.2 安全
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 各端登录(admin / user / company / doctor)
|
|
|
|
|
+- [ ] JWT 过期与刷新
|
|
|
|
|
+- [ ] 权限注解 `@PreAuthorize`
|
|
|
|
|
+- [ ] 匿名白名单(支付回调、企微回调、物流回调)
|
|
|
|
|
+
|
|
|
|
|
+### 9.3 业务链路
|
|
|
|
|
+
|
|
|
|
|
+- [ ] 下单 → 支付 → 回调
|
|
|
|
|
+- [ ] 售后 / 退款
|
|
|
|
|
+- [ ] 课程观看 / 完播任务(fs-qw-task)
|
|
|
|
|
+- [ ] 企微 SOP / 消息推送
|
|
|
|
|
+- [ ] 直播下单 / 购物车
|
|
|
|
|
+- [ ] 文件上传 OSS
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 十、推荐执行步骤汇总
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+阶段 0 建分支、打基线、确认回滚方案
|
|
|
|
|
+ ↓
|
|
|
|
|
+阶段 1 升 BOM 2.7.18 → Redisson 27 → MyBatis-Plus → 删 spring-expression 6.2.0
|
|
|
|
|
+ ↓ 统一 spring-boot-maven-plugin
|
|
|
|
|
+ ↓
|
|
|
|
|
+阶段 2 application-common.yml 加 circular-ref + ant_path_matcher
|
|
|
|
|
+ ↓
|
|
|
|
|
+阶段 3 重构 SecurityConfig(先 fs-framework,再各模块)
|
|
|
|
|
+ ↓ 评估删除 fs-common Security 补丁
|
|
|
|
|
+ ↓
|
|
|
|
|
+阶段 4 验证 Springfox(或排期 springdoc)
|
|
|
|
|
+ ↓
|
|
|
|
|
+阶段 5 mvn compile → 按 P0→P2 逐个启动修错
|
|
|
|
|
+ ↓
|
|
|
|
|
+阶段 6 全链路回归 → 预发验证 → 生产灰度
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 十一、不在本次范围内
|
|
|
|
|
+
|
|
|
|
|
+以下内容属于 **Spring Boot 3.x** 范畴,本次 **2.7.18 不需要做**:
|
|
|
|
|
+
|
|
|
|
|
+- Java 17+ 升级
|
|
|
|
|
+- `javax.*` → `jakarta.*` 包名替换
|
|
|
|
|
+- Spring Security 6.x API
|
|
|
|
|
+- Redisson `spring-data-32`
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 十二、参考链接
|
|
|
|
|
+
|
|
|
|
|
+- [Spring Boot 2.7 Release Notes](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Release-Notes)
|
|
|
|
|
+- [Spring Boot 2.7 Migration Guide](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.7-Migration-Guide)
|
|
|
|
|
+- [Spring Security 5.7 Migration](https://docs.spring.io/spring-security/reference/5.8/migration/servlet/config.html)
|
|
|
|
|
+- [Spring Boot 2.6 PathPattern 变更说明](https://spring.io/blog/2020/06/30/url-matching-with-pathpattern-in-spring-mvc)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+*文档生成日期:2026-06-08*
|