升级springboot4

This commit is contained in:
JEECG 2026-07-07 13:41:42 +08:00
parent 317a26253e
commit bd97aad26b
17 changed files with 85 additions and 160 deletions

View File

@ -65,10 +65,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
@ -104,7 +104,7 @@
<!-- mybatis-plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
@ -121,15 +121,19 @@
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>${druid.version}</version>
<artifactId>druid-spring-boot-4-starter</artifactId>
<version>1.2.28</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 动态数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<version>${dynamic-datasource-spring-boot-starter.version}</version>
<artifactId>dynamic-datasource-spring-boot4-starter</artifactId>
<version>4.5.0</version>
</dependency>
<!-- 数据库驱动 -->

View File

@ -111,7 +111,7 @@ public class RestDesformUtil {
private static HttpHeaders getHeaders(String token) {
HttpHeaders headers = new HttpHeaders();
String mediaType = MediaType.APPLICATION_JSON_UTF8_VALUE;
String mediaType = MediaType.APPLICATION_JSON_VALUE;
headers.setContentType(MediaType.parseMediaType(mediaType));
headers.set("Accept", mediaType);
headers.set("X-Access-Token", token);

View File

@ -61,7 +61,7 @@ public class RestUtil {
// 解决[issues/8859]online表单java增强失效------------
// 使用 Apache HttpClient 避免 JDK HttpURLConnection too many bytes written 问题
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setConnectTimeout(30000);
requestFactory.setConnectionRequestTimeout(30000);
requestFactory.setReadTimeout(30000);
RT = new RestTemplate(requestFactory);
// 解决乱码问题替换 StringHttpMessageConverter UTF-8
@ -271,7 +271,7 @@ public class RestUtil {
if (timeout > 0) {
// 代码逻辑说明: [issues/8859]online表单java增强失效------------
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
requestFactory.setConnectTimeout(timeout);
requestFactory.setConnectionRequestTimeout(timeout);
requestFactory.setReadTimeout(timeout);
restTemplate = new RestTemplate(requestFactory);
// 解决乱码问题替换 StringHttpMessageConverter UTF-8
@ -299,7 +299,7 @@ public class RestUtil {
}
// Content-Length 强制设置解决可能出现的截断问题
if (StringUtils.isNotEmpty(body) && !headers.containsKey(HttpHeaders.CONTENT_LENGTH)) {
if (StringUtils.isNotEmpty(body) && !headers.containsHeader(HttpHeaders.CONTENT_LENGTH)) {
int contentLength = body.getBytes(StandardCharsets.UTF_8).length;
String current = headers.getFirst(HttpHeaders.CONTENT_LENGTH);
if (current == null || !current.equals(String.valueOf(contentLength))) {
@ -317,7 +317,7 @@ public class RestUtil {
* 获取JSON请求头
*/
public static HttpHeaders getHeaderApplicationJson() {
return getHeader(MediaType.APPLICATION_JSON_UTF8_VALUE);
return getHeader(MediaType.APPLICATION_JSON_VALUE);
}
/**

View File

@ -2,8 +2,8 @@ package org.jeecg.config;
import java.io.IOException;
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure;
import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.spring.boot4.autoconfigure.DruidDataSourceAutoConfigure;
import com.alibaba.druid.spring.boot4.autoconfigure.properties.DruidStatProperties;
import jakarta.servlet.*;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;

View File

@ -23,14 +23,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.boot.data.redis.autoconfigure.DataRedisProperties;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import redis.clients.jedis.HostAndPort;
@ -55,8 +52,10 @@ public class ShiroConfig {
private Environment env;
@Resource
private JeecgBaseConfig jeecgBaseConfig;
//update-begin---author:scott ---date:2026-07-07 forSpring Boot 4.0 升级RedisProperties 改名为 DataRedisProperties包路径变更-----------
@Autowired(required = false)
private RedisProperties redisProperties;
private DataRedisProperties redisProperties;
//update-end---author:scott ---date:2026-07-07 forSpring Boot 4.0 升级RedisProperties 改名为 DataRedisProperties包路径变更-----------
/**
* Filter Chain定义说明
@ -327,6 +326,7 @@ public class ShiroConfig {
public IRedisManager redisManager() {
log.info("===============(2)创建RedisManager,连接Redis..");
IRedisManager manager;
//update-begin---author:scott ---date:2026-07-07 forSpring Boot 4.0 升级恢复 Sentinel 哨兵模式支持API 兼容-----------
// sentinel cluster redisissues/5569shiro集成 redis 不支持 sentinel 方式部署的redis集群 #5569
if (Objects.nonNull(redisProperties)
&& Objects.nonNull(redisProperties.getSentinel())
@ -339,6 +339,7 @@ public class ShiroConfig {
return sentinelManager;
}
//update-end---author:scott ---date:2026-07-07 forSpring Boot 4.0 升级恢复 Sentinel 哨兵模式支持API 兼容-----------
// redis 单机支持在集群为空或者集群无机器时候使用 add by jzyadmin@163.com
if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {

View File

@ -326,7 +326,7 @@ public class PluginToolBuilder {
}
// 如果请求体不为空且没有设置Content-Type默认设置为application/json
if (!httpHeaders.containsKey(HttpHeaders.CONTENT_TYPE)) {
if (!httpHeaders.containsHeader(HttpHeaders.CONTENT_TYPE)) {
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
}

View File

@ -2,7 +2,7 @@ package org.jeecg.config.init;
import org.apache.catalina.Context;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

View File

@ -1,7 +1,7 @@
package org.jeecg.modules.monitor.actuator;
import org.jeecg.modules.monitor.actuator.httptrace.CustomInMemoryHttpTraceRepository;
import org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesEndpointAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesProperties;
import org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
@ -19,7 +19,7 @@ import org.springframework.context.annotation.Configuration;
*/
@Configuration
@EnableConfigurationProperties(HttpExchangesProperties.class)
@AutoConfigureBefore(HttpExchangesAutoConfiguration.class)
@AutoConfigureBefore(HttpExchangesEndpointAutoConfiguration.class)
public class CustomActuatorConfig {
/**

View File

@ -1,7 +1,7 @@
package org.jeecg.modules.monitor.service.impl;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.health.contributor.Health;
import org.springframework.boot.health.contributor.HealthIndicator;
import org.springframework.stereotype.Component;
/**

View File

@ -195,7 +195,7 @@ public class OpenApiController extends JeecgController<OpenApi, OpenApiService>
url = CommonUtils.getBaseUrl(request) + url;
}
//update-end---author:scott ---date:20260429 forissues/9590微服务nginx部署openApi接口访问不到-----------
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(url);
if (HttpMethod.GET.matches(method)
|| HttpMethod.DELETE.matches(method)
|| HttpMethod.OPTIONS.matches(method)

View File

@ -6,7 +6,6 @@ import org.jeecg.common.util.oConvertUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.ConfigurableApplicationContext;
@ -22,7 +21,6 @@ import java.util.Map;
* 报错提醒: 未集成mongo报错可以打开启动类上面的注释 exclude={MongoAutoConfiguration.class}
*/
@Slf4j
@SpringBootApplication(exclude = MongoAutoConfiguration.class)
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
public class JeecgSystemApplication extends SpringBootServletInitializer {
@ -38,7 +36,7 @@ public class JeecgSystemApplication extends SpringBootServletInitializer {
app.setDefaultProperties(defaultProperties);
log.info("[JEECG] Elasticsearch Health Check Enabled: false" );
ConfigurableApplicationContext application = app.run(args);;
ConfigurableApplicationContext application = app.run(args);
Environment env = application.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");

View File

@ -2,10 +2,6 @@ server:
port: 8080
tomcat:
max-swallow-size: -1
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
servlet:
context-path: /jeecg-boot
compression:
@ -20,9 +16,14 @@ management:
include: metrics,httpexchanges,jeecghttptrace
spring:
# main:
# # 启动加速 (建议开发环境开启后flyway自动升级失效)
# lazy-initialization: true
# main:
# # 启动加速 (建议开发环境开启后flyway自动升级失效)
# lazy-initialization: true
web:
error:
include-exception: true
include-stacktrace: ALWAYS
include-message: ALWAYS
flyway:
# 是否启用flyway
enabled: false

View File

@ -52,6 +52,6 @@ public class JeecgGatewayApplication implements CommandLineRunner {
*/
@Bean
public RouterFunction<ServerResponse> indexRouter(@Value("classpath:/META-INF/resources/doc.html") final org.springframework.core.io.Resource indexHtml) {
return route(GET("/"), request -> ok().contentType(MediaType.TEXT_HTML).syncBody(indexHtml));
return route(GET("/"), request -> ok().contentType(MediaType.TEXT_HTML).bodyValue(indexHtml));
}
}

View File

@ -50,7 +50,7 @@
<!--undertow容器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
</dependencies>

View File

@ -1,6 +1,7 @@
package org.jeecg.monitor.config;
import de.codecentric.boot.admin.server.config.AdminServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
@ -20,39 +21,40 @@ public class SecuritySecureConfig {
this.adminContextPath = adminServerProperties.getContextPath();
}
@Bean
public SecurityFilterChain configure(HttpSecurity http) throws Exception {
// 登录成功处理类
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
successHandler.setTargetUrlParameter("redirectTo");
successHandler.setDefaultTargetUrl(adminContextPath + "/");
http.authorizeRequests(authorize -> {
try {
authorize
//静态文件允许访问
.requestMatchers(adminContextPath + "/assets/**").permitAll()
//登录页面允许访问
.requestMatchers(adminContextPath + "/login", "/css/**", "/js/**", "/image/*").permitAll()
//其他所有请求需要登录
.anyRequest().authenticated()
.and()
//登录页面配置用于替换security默认页面
.formLogin(formLogin -> formLogin.loginPage(adminContextPath + "/login").successHandler(successHandler))
//登出页面配置用于替换security默认页面
.logout(logout -> logout.logoutUrl(adminContextPath + "/logout"))
.httpBasic(Customizer.withDefaults())
.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(
"/instances",
"/actuator/**")
);
} catch (Exception e) {
e.printStackTrace();
}
}
);
http
// authorizeRequests() 已废弃,使用 authorizeHttpRequests()
.authorizeHttpRequests(authorize -> authorize
//静态文件允许访问
.requestMatchers(adminContextPath + "/assets/**").permitAll()
//登录页面允许访问
.requestMatchers(adminContextPath + "/login", "/css/**", "/js/**", "/image/*").permitAll()
//其他所有请求需要登录
.anyRequest().authenticated()
)
//登录页面配置用于替换security默认页面
.formLogin(formLogin -> formLogin
.loginPage(adminContextPath + "/login")
.successHandler(successHandler)
)
//登出页面配置用于替换security默认页面
.logout(logout -> logout
.logoutUrl(adminContextPath + "/logout")
)
.httpBasic(Customizer.withDefaults())
.csrf(csrf -> csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.ignoringRequestMatchers(
"/instances",
"/actuator/**"
)
);
return http.build();

View File

@ -1,92 +0,0 @@
package com.xxl.job.admin.core.util;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
* Jackson util
*
* 1obj need private and set/get
* 2do not support inner class
*
* @author xuxueli 2015-9-25 18:02:56
*/
public class JacksonUtil {
private static Logger logger = LoggerFactory.getLogger(JacksonUtil.class);
private final static ObjectMapper objectMapper = new ObjectMapper();
public static ObjectMapper getInstance() {
return objectMapper;
}
/**
* beanarrayListMap --> json
*
* @param obj
* @return json string
* @throws Exception
*/
public static String writeValueAsString(Object obj) {
try {
return getInstance().writeValueAsString(obj);
} catch (JsonGenerationException e) {
logger.error(e.getMessage(), e);
} catch (JsonMappingException e) {
logger.error(e.getMessage(), e);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
/**
* string --> beanMapList(array)
*
* @param jsonStr
* @param clazz
* @return obj
* @throws Exception
*/
public static <T> T readValue(String jsonStr, Class<T> clazz) {
try {
return getInstance().readValue(jsonStr, clazz);
} catch (JsonParseException e) {
logger.error(e.getMessage(), e);
} catch (JsonMappingException e) {
logger.error(e.getMessage(), e);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
/**
* string --> List<Bean>...
*
* @param jsonStr
* @param parametrized
* @param parameterClasses
* @param <T>
* @return
*/
public static <T> T readValue(String jsonStr, Class<?> parametrized, Class<?>... parameterClasses) {
try {
JavaType javaType = getInstance().getTypeFactory().constructParametricType(parametrized, parameterClasses);
return getInstance().readValue(jsonStr, javaType);
} catch (JsonParseException e) {
logger.error(e.getMessage(), e);
} catch (JsonMappingException e) {
logger.error(e.getMessage(), e);
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
return null;
}
}

View File

@ -23,7 +23,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.5</version>
<version>4.1.0</version>
<relativePath/>
</parent>
@ -34,8 +34,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 微服务 -->
<spring-cloud.version>2025.0.0</spring-cloud.version>
<spring-cloud-alibaba.version>2023.0.3.3</spring-cloud-alibaba.version>
<spring-cloud.version>2025.1.2</spring-cloud.version>
<spring-cloud-alibaba.version>2025.1.0.0</spring-cloud-alibaba.version>
<alibaba.nacos.version>2.0.4</alibaba.nacos.version>
<xxl-job-core.version>2.4.1</xxl-job-core.version>
@ -118,6 +118,16 @@
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>github</id>
<url>https://maven.pkg.github.com/alibaba/spring-cloud-alibaba</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
@ -225,6 +235,7 @@
<artifactId>jeecg-boot-starter-job</artifactId>
<version>3.9.2</version>
</dependency>
<!--redis分布式锁-->
<dependency>
<groupId>org.jeecgframework.boot3</groupId>