!46 Spring Boot升级至4.0.1
Merge pull request !46 from 太空眼睛/master-upgrade-springboot4
This commit is contained in:
22
pom.xml
22
pom.xml
@@ -12,7 +12,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>3.5.6</version> <!-- lookup parent from repository -->
|
<version>4.0.1</version> <!-- lookup parent from repository -->
|
||||||
<relativePath/>
|
<relativePath/>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
@@ -24,7 +24,8 @@
|
|||||||
|
|
||||||
<mysql-connector-j.version>9.1.0</mysql-connector-j.version>
|
<mysql-connector-j.version>9.1.0</mysql-connector-j.version>
|
||||||
<druid.version>1.2.24</druid.version>
|
<druid.version>1.2.24</druid.version>
|
||||||
<mybatis-plus.version>3.5.5</mybatis-plus.version>
|
<!-- Spring Boot 4.x 必须使用更新的版本 -->
|
||||||
|
<mybatis-plus.version>3.5.15</mybatis-plus.version>
|
||||||
<dynamic-datasource.version>4.3.1</dynamic-datasource.version>
|
<dynamic-datasource.version>4.3.1</dynamic-datasource.version>
|
||||||
|
|
||||||
<knife4j.version>4.5.0</knife4j.version>
|
<knife4j.version>4.5.0</knife4j.version>
|
||||||
@@ -43,7 +44,8 @@
|
|||||||
<aliyun-sdk-oss.version>3.16.3</aliyun-sdk-oss.version>
|
<aliyun-sdk-oss.version>3.16.3</aliyun-sdk-oss.version>
|
||||||
|
|
||||||
<!-- redisson 分布式锁 -->
|
<!-- redisson 分布式锁 -->
|
||||||
<redisson.version>3.51.0</redisson.version>
|
<!-- Spring Boot 4.x 必须使用更新的版本 -->
|
||||||
|
<redisson.version>4.1.0</redisson.version>
|
||||||
|
|
||||||
<!-- 自动代码生成 -->
|
<!-- 自动代码生成 -->
|
||||||
<mybatis-plus-generator.version>3.5.6</mybatis-plus-generator.version>
|
<mybatis-plus-generator.version>3.5.6</mybatis-plus-generator.version>
|
||||||
@@ -63,7 +65,8 @@
|
|||||||
<!-- 阿里 TransmittableThreadLocal (支持异步场景的ThreadLocal传递) -->
|
<!-- 阿里 TransmittableThreadLocal (支持异步场景的ThreadLocal传递) -->
|
||||||
<transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
|
<transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
|
||||||
|
|
||||||
<spring-ai-openai.version>1.1.2</spring-ai-openai.version>
|
<!-- Spring Boot 4.x 必须使用更新的版本 -->
|
||||||
|
<spring-ai-openai.version>2.0.0-M1</spring-ai-openai.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -121,9 +124,10 @@
|
|||||||
<artifactId>spring-boot-starter-cache</artifactId>
|
<artifactId>spring-boot-starter-cache</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring Boot 4.x 已改名 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-aop</artifactId>
|
<artifactId>spring-boot-starter-aspectj</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@@ -154,9 +158,15 @@
|
|||||||
<version>${druid.version}</version>
|
<version>${druid.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Spring Boot 4.x 必须使用boot4版本 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<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>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||||
<version>${mybatis-plus.version}</version>
|
<version>${mybatis-plus.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.youlai.boot.config;
|
package com.youlai.boot.config;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.cache.CacheProperties;
|
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.cache.autoconfigure.CacheProperties;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.cache.annotation.EnableCaching;
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
package com.youlai.boot.config;
|
package com.youlai.boot.config;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
|
||||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
|
|
||||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
|
|
||||||
import jakarta.validation.Validation;
|
import jakarta.validation.Validation;
|
||||||
import jakarta.validation.Validator;
|
import jakarta.validation.Validator;
|
||||||
import jakarta.validation.ValidatorFactory;
|
import jakarta.validation.ValidatorFactory;
|
||||||
@@ -15,16 +8,18 @@ import org.hibernate.validator.HibernateValidator;
|
|||||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.converter.HttpMessageConverter;
|
import org.springframework.http.converter.HttpMessageConverters;
|
||||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||||
import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory;
|
import org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
import tools.jackson.databind.cfg.DateTimeFeature;
|
||||||
|
import tools.jackson.databind.json.JsonMapper;
|
||||||
|
import tools.jackson.databind.module.SimpleModule;
|
||||||
|
import tools.jackson.databind.ser.std.ToStringSerializer;
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.List;
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,36 +35,27 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置消息转换器
|
* Spring Boot 4.x 已经使用Jackson 3.x
|
||||||
|
* Jackson 3.x已经自带JavaTimeModule,不再需要手工注册
|
||||||
*
|
*
|
||||||
* @param converters 消息转换器列表
|
* @param converterBuilder the builder to configure
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
public void configureMessageConverters(HttpMessageConverters.ServerBuilder converterBuilder) {
|
||||||
MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
|
JsonMapper.Builder builder = JsonMapper.builder();
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
|
|
||||||
// 注册 JavaTimeModule(替代手动注册 LocalDateTimeSerializer)
|
|
||||||
JavaTimeModule javaTimeModule = new JavaTimeModule();
|
|
||||||
// 返回指定字符串格式
|
|
||||||
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DATE_TIME_FORMATTER));
|
|
||||||
// 反序列化,接受前端传来的格式
|
|
||||||
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DATE_TIME_FORMATTER));
|
|
||||||
objectMapper.registerModule(javaTimeModule);
|
|
||||||
|
|
||||||
// 配置全局日期格式和时区
|
// 配置全局日期格式和时区
|
||||||
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
builder.disable(DateTimeFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||||
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
|
builder.defaultDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
|
||||||
objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
|
builder.defaultTimeZone(TimeZone.getTimeZone("GMT+8"));
|
||||||
|
|
||||||
// 处理 Long/BigInteger 的精度问题
|
// 处理 Long/BigInteger 的精度问题
|
||||||
SimpleModule simpleModule = new SimpleModule();
|
SimpleModule simpleModule = new SimpleModule();
|
||||||
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
|
simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
|
||||||
simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
|
simpleModule.addSerializer(BigInteger.class, ToStringSerializer.instance);
|
||||||
objectMapper.registerModule(simpleModule);
|
builder.addModule(simpleModule);
|
||||||
|
|
||||||
jackson2HttpMessageConverter.setObjectMapper(objectMapper);
|
converterBuilder.addCustomConverter(new JacksonJsonHttpMessageConverter(builder));
|
||||||
converters.add(1, jackson2HttpMessageConverter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.youlai.boot.core.exception;
|
package com.youlai.boot.core.exception;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import tools.jackson.core.JacksonException;
|
||||||
import com.youlai.boot.core.web.Result;
|
import com.youlai.boot.core.web.Result;
|
||||||
import com.youlai.boot.core.web.ResultCode;
|
import com.youlai.boot.core.web.ResultCode;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
@@ -143,11 +143,11 @@ public class GlobalExceptionHandler {
|
|||||||
/**
|
/**
|
||||||
* 处理 JSON 处理异常
|
* 处理 JSON 处理异常
|
||||||
* <p>
|
* <p>
|
||||||
* 当处理 JSON 数据时发生错误,会抛出 JsonProcessingException 异常。
|
* 当处理 JSON 数据时发生错误,会抛出 JacksonException 异常。
|
||||||
*/
|
*/
|
||||||
@ExceptionHandler(JsonProcessingException.class)
|
@ExceptionHandler(JacksonException.class)
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
public <T> Result<T> handleJsonProcessingException(JsonProcessingException e) {
|
public <T> Result<T> handleJacksonException(JacksonException e) {
|
||||||
log.error("Json转换异常,异常原因:{}", e.getMessage(), e);
|
log.error("Json转换异常,异常原因:{}", e.getMessage(), e);
|
||||||
return Result.failed(e.getMessage());
|
return Result.failed(e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package com.youlai.boot.platform.websocket.publisher;
|
package com.youlai.boot.platform.websocket.publisher;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
import org.springframework.messaging.simp.SimpMessagingTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import tools.jackson.core.JacksonException;
|
||||||
|
import tools.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -49,7 +49,7 @@ public class WebSocketPublisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object serializeIfNeeded(Object payload) throws JsonProcessingException {
|
private Object serializeIfNeeded(Object payload) throws JacksonException {
|
||||||
if (payload == null) {
|
if (payload == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* WebSocket 服务实现类
|
* WebSocket 服务实现类
|
||||||
*
|
*
|
||||||
* 核心功能:
|
* 核心功能:
|
||||||
* - 用户在线状态管理(支持多设备登录)
|
* - 用户在线状态管理(支持多设备登录)
|
||||||
* - 消息推送(广播、点对点)
|
* - 消息推送(广播、点对点)
|
||||||
@@ -145,7 +145,7 @@ public class WebSocketServiceImpl implements WebSocketService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 手动触发在线用户数量广播
|
* 手动触发在线用户数量广播
|
||||||
*
|
*
|
||||||
* 供外部服务(如定时任务)调用
|
* 供外部服务(如定时任务)调用
|
||||||
*/
|
*/
|
||||||
public void notifyOnlineUsersChange() {
|
public void notifyOnlineUsersChange() {
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class CaptchaValidationFilter extends OncePerRequestFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 包装请求,确保下游还能读取 body
|
// 包装请求,确保下游还能读取 body
|
||||||
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
|
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request, -1);
|
||||||
|
|
||||||
byte[] bodyBytes = StreamUtils.copyToByteArray(requestWrapper.getInputStream());
|
byte[] bodyBytes = StreamUtils.copyToByteArray(requestWrapper.getInputStream());
|
||||||
String body = new String(bodyBytes, StandardCharsets.UTF_8);
|
String body = new String(bodyBytes, StandardCharsets.UTF_8);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class SmsAuthenticationToken extends AbstractAuthenticationToken {
|
|||||||
*/
|
*/
|
||||||
public SmsAuthenticationToken(Object principal, Object credentials) {
|
public SmsAuthenticationToken(Object principal, Object credentials) {
|
||||||
// 没有授权信息时,设置为 null
|
// 没有授权信息时,设置为 null
|
||||||
super(null);
|
super((Collection<? extends GrantedAuthority>) null);
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
// 默认未认证
|
// 默认未认证
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class WxMiniAppCodeAuthenticationToken extends AbstractAuthenticationToke
|
|||||||
*/
|
*/
|
||||||
public WxMiniAppCodeAuthenticationToken(Object principal) {
|
public WxMiniAppCodeAuthenticationToken(Object principal) {
|
||||||
// 没有授权信息时,设置为 null
|
// 没有授权信息时,设置为 null
|
||||||
super(null);
|
super((Collection<? extends GrantedAuthority>) null);
|
||||||
this.principal = principal;
|
this.principal = principal;
|
||||||
// 默认未认证
|
// 默认未认证
|
||||||
this.setAuthenticated(false);
|
this.setAuthenticated(false);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class WxMiniAppPhoneAuthenticationToken extends AbstractAuthenticationTok
|
|||||||
* @param iv 初始向量
|
* @param iv 初始向量
|
||||||
*/
|
*/
|
||||||
public WxMiniAppPhoneAuthenticationToken(String code, String encryptedData, String iv) {
|
public WxMiniAppPhoneAuthenticationToken(String code, String encryptedData, String iv) {
|
||||||
super(null);
|
super((Collection<? extends GrantedAuthority>) null);
|
||||||
this.principal = code;
|
this.principal = code;
|
||||||
this.encryptedData = encryptedData;
|
this.encryptedData = encryptedData;
|
||||||
this.iv = iv;
|
this.iv = iv;
|
||||||
|
|||||||
@@ -8,8 +8,8 @@ import cn.hutool.json.JSONUtil;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import tools.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import tools.jackson.databind.ObjectMapper;
|
||||||
import com.youlai.boot.platform.codegen.model.entity.GenTable;
|
import com.youlai.boot.platform.codegen.model.entity.GenTable;
|
||||||
import com.youlai.boot.security.util.SecurityUtils;
|
import com.youlai.boot.security.util.SecurityUtils;
|
||||||
import com.youlai.boot.system.converter.MenuConverter;
|
import com.youlai.boot.system.converter.MenuConverter;
|
||||||
|
|||||||
Reference in New Issue
Block a user