feat: Spring Boot 3.5.14 → 4.0.6 升级

核心升级:
- Spring Boot 3.5.14 → 4.0.6
- Spring Framework 6.2.18 → 7.0.7
- Spring Security 6.5.10 → 7.0.5
- Flyway 11.7.2 → 11.14.1

Breaking Changes 适配:
- starter-aop → starter-aspectj (SB4 重命名)
- JDBC/Flyway/Jackson 自动配置拆分到独立模块
- DaoAuthenticationProvider 构造函数变更 (Spring Security 7.0)
- DataSourceProperties 包路径迁移

依赖调整:
- Druid boot3-starter → druid core (手动配置, 避免 SB4 不兼容)
- 新增 spring-boot-starter-quartz
- 新增 spring-boot-starter-cache
- 新增 spring-boot-flyway / spring-boot-jdbc
- PostgreSQL 42.7.4 → 42.7.10

验证: 26/26 测试通过, 1374 API端点正常
This commit is contained in:
2026-06-05 08:43:30 +08:00
parent 1d21661a78
commit 554e20f276
13 changed files with 461 additions and 65 deletions

View File

@@ -28,13 +28,20 @@
<!-- SpringBoot 拦截器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<artifactId>spring-boot-starter-aspectj</artifactId>
</dependency>
<!-- SB4: Jackson 自动配置拆分到独立模块 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-jackson2</artifactId>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 验证码 -->
@@ -60,6 +67,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- 系统模块-->
<dependency>

View File

@@ -6,7 +6,7 @@ import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.jackson2.autoconfigure.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

View File

@@ -1,8 +1,6 @@
package com.core.framework.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import com.core.common.enums.DataSourceType;
import com.core.common.utils.spring.SpringUtils;
@@ -21,17 +19,12 @@ import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* druid 配置多数据源
*
* @author system
*/
@Configuration
public class DruidConfig {
@Bean
@ConfigurationProperties("spring.datasource.druid.master")
public DataSource masterDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
DruidDataSource dataSource = new DruidDataSource();
return druidProperties.dataSource(dataSource);
}
@@ -39,7 +32,7 @@ public class DruidConfig {
@ConfigurationProperties("spring.datasource.druid.slave")
@ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
public DataSource slaveDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
DruidDataSource dataSource = new DruidDataSource();
return druidProperties.dataSource(dataSource);
}
@@ -52,13 +45,6 @@ public class DruidConfig {
return new DynamicDataSource(masterDataSource, targetDataSources);
}
/**
* 设置数据源
*
* @param targetDataSources 备选数据源集合
* @param sourceName 数据源名称
* @param beanName bean名称
*/
public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName) {
try {
DataSource dataSource = SpringUtils.getBean(beanName);
@@ -67,20 +53,10 @@ public class DruidConfig {
}
}
/**
* 去除监控页面底部的广告
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) {
// 获取web监控页面的参数
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
// 提取common.js的配置路径
String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
final String filePath = "support/http/resources/js/common.js";
// 创建filter进行过滤
public FilterRegistrationBean removeDruidFilterRegistrationBean() {
Filter filter = new Filter() {
@Override
public void init(jakarta.servlet.FilterConfig filterConfig) throws ServletException {}
@@ -89,11 +65,8 @@ public class DruidConfig {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
// 重置缓冲区,响应头不会被重置
response.resetBuffer();
// 获取common.js
String text = Utils.readFromResource(filePath);
// 正则替换banner, 除去底部的广告信息
String text = Utils.readFromResource("support/http/resources/js/common.js");
text = text.replaceAll("<a.*?banner\"></a><br/>", "");
text = text.replaceAll("powered.*?shrek.wang</a>", "");
response.getWriter().write(text);
@@ -104,7 +77,7 @@ public class DruidConfig {
};
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter);
registrationBean.addUrlPatterns(commonJsPattern);
registrationBean.addUrlPatterns("/druid/js/common.js");
return registrationBean;
}
}

View File

@@ -70,8 +70,7 @@ public class SecurityConfig {
*/
@Bean
public AuthenticationManager authenticationManager() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService);
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider(userDetailsService);
daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
return new ProviderManager(daoAuthenticationProvider);
}