# Conflicts:
#	README.md
#	pom.xml
#	yudao-dependencies/pom.xml
This commit is contained in:
YunaiV
2025-08-29 09:24:09 +08:00
14 changed files with 84 additions and 64 deletions

View File

@@ -31,11 +31,11 @@
<mybatis-plus-join.version>1.5.4</mybatis-plus-join.version>
<dynamic-datasource.version>4.3.1</dynamic-datasource.version>
<easy-trans.version>3.0.6</easy-trans.version>
<redisson.version>3.50.0</redisson.version>
<redisson.version>3.51.0</redisson.version>
<dm8.jdbc.version>8.1.3.140</dm8.jdbc.version>
<kingbase.jdbc.version>8.6.0</kingbase.jdbc.version>
<opengauss.jdbc.version>5.1.0</opengauss.jdbc.version>
<taos.version>3.3.3</taos.version>
<taos.version>3.7.3</taos.version>
<!-- 消息队列 -->
<rocketmq-spring.version>2.3.4</rocketmq-spring.version>
<!-- 服务保障相关 -->
@@ -52,11 +52,11 @@
<flowable.version>6.8.0</flowable.version>
<!-- 工具类相关 -->
<anji-plus-captcha.version>1.4.0</anji-plus-captcha.version>
<jsoup.version>1.21.1</jsoup.version>
<jsoup.version>1.21.2</jsoup.version>
<lombok.version>1.18.38</lombok.version>
<mapstruct.version>1.6.3</mapstruct.version>
<hutool.version>5.8.39</hutool.version>
<fastexcel.version>1.2.0</fastexcel.version>
<hutool-5.version>5.8.40</hutool-5.version>
<fastexcel.version>1.3.0</fastexcel.version>
<velocity.version>2.4</velocity.version> <!-- JDK8 不能从 2.4 升级到 2.4.1,会报包不存在!!!! -->
<fastjson.version>1.2.83</fastjson.version>
<guava.version>33.4.8-jre</guava.version>
@@ -77,7 +77,7 @@
<justauth-starter.version>1.4.0</justauth-starter.version>
<jimureport.version>2.1.0</jimureport.version>
<jimubi.version>1.9.5</jimubi.version>
<weixin-java.version>4.7.5.B</weixin-java.version>
<weixin-java.version>4.7.7-20250808.182223</weixin-java.version>
<!-- 专属于 JDK8 安全漏洞升级 -->
<logback.version>1.2.13</logback.version> <!-- 无法使用 1.3.X 版本,启动会报错 -->
</properties>

View File

@@ -75,7 +75,7 @@ public class TenantDatabaseInterceptor implements TenantLineHandler {
if (TenantBaseDO.class.isAssignableFrom(tableInfo.getEntityType())) {
return false;
}
// 如果添加了 @TenantIgnore 注解,显然也不忽略租户
// 如果添加了 @TenantIgnore 注解,忽略租户
TenantIgnore tenantIgnore = tableInfo.getEntityType().getAnnotation(TenantIgnore.class);
return tenantIgnore != null;
}

View File

@@ -13,11 +13,10 @@ public class TenantRabbitMQInitializer implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof RabbitTemplate) {
RabbitTemplate rabbitTemplate = (RabbitTemplate) bean;
if (bean instanceof RabbitTemplate rabbitTemplate) {
rabbitTemplate.addBeforePublishPostProcessors(new TenantRabbitMQMessagePostProcessor());
}
return bean;
}
}
}

View File

@@ -18,11 +18,9 @@ public class TenantRocketMQInitializer implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof DefaultRocketMQListenerContainer) {
DefaultRocketMQListenerContainer container = (DefaultRocketMQListenerContainer) bean;
if (bean instanceof DefaultRocketMQListenerContainer container) {
initTenantConsumer(container.getConsumer());
} else if (bean instanceof RocketMQTemplate) {
RocketMQTemplate template = (RocketMQTemplate) bean;
} else if (bean instanceof RocketMQTemplate template) {
initTenantProducer(template.getProducer());
}
return bean;
@@ -50,4 +48,4 @@ public class TenantRocketMQInitializer implements BeanPostProcessor {
consumerImpl.registerConsumeMessageHook(new TenantRocketMQConsumeMessageHook());
}
}
}

View File

@@ -23,15 +23,13 @@ public class YudaoAsyncAutoConfiguration {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 处理 ThreadPoolTaskExecutor
if (bean instanceof ThreadPoolTaskExecutor) {
ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean;
if (bean instanceof ThreadPoolTaskExecutor executor) {
executor.setTaskDecorator(TtlRunnable::get);
return executor;
}
// 处理 SimpleAsyncTaskExecutor
// 参考 https://t.zsxq.com/CBoks 增加
if (bean instanceof SimpleAsyncTaskExecutor) {
SimpleAsyncTaskExecutor executor = (SimpleAsyncTaskExecutor) bean;
if (bean instanceof SimpleAsyncTaskExecutor executor) {
executor.setTaskDecorator(TtlRunnable::get);
return executor;
}

View File

@@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.extension.incrementer.*;
import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
import com.baomidou.mybatisplus.extension.parser.cache.JdkSerialCaffeineJsqlParseCache;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.apache.ibatis.annotations.Mapper;
import org.mybatis.spring.annotation.MapperScan;
@@ -42,6 +43,7 @@ public class YudaoMybatisAutoConfiguration {
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); // 分页插件
mybatisPlusInterceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 拦截没有指定条件的 update 和 delete 语句
return mybatisPlusInterceptor;
}

View File

@@ -19,8 +19,7 @@ public class DefaultDBFieldHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();
if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO baseDO) {
LocalDateTime current = LocalDateTime.now();
// 创建时间为空,则以当前时间为插入时间

View File

@@ -1,10 +1,10 @@
package cn.iocoder.yudao.framework.jackson.config;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.framework.common.util.json.databind.NumberSerializer;
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer;
import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
@@ -13,39 +13,65 @@ import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
import org.springframework.context.annotation.Bean;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
@AutoConfiguration
@AutoConfiguration(after = JacksonAutoConfiguration.class)
@Slf4j
public class YudaoJacksonAutoConfiguration {
/**
* 从 Builder 源头定制(关键:使用 *ByType避免 handledType 要求)
*/
@Bean
public Jackson2ObjectMapperBuilderCustomizer ldtEpochMillisCustomizer() {
return builder -> builder
// Long -> Number
.serializerByType(Long.class, NumberSerializer.INSTANCE)
.serializerByType(Long.TYPE, NumberSerializer.INSTANCE)
// LocalDate / LocalTime
.serializerByType(LocalDate.class, LocalDateSerializer.INSTANCE)
.deserializerByType(LocalDate.class, LocalDateDeserializer.INSTANCE)
.serializerByType(LocalTime.class, LocalTimeSerializer.INSTANCE)
.deserializerByType(LocalTime.class, LocalTimeDeserializer.INSTANCE)
// LocalDateTime < - > EpochMillis
.serializerByType(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
.deserializerByType(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
}
/**
* 以 Bean 形式暴露 ModuleBoot 会自动注册到所有 ObjectMapper
*/
@Bean
public Module timestampSupportModuleBean() {
SimpleModule m = new SimpleModule("TimestampSupportModule");
// Long -> Number避免前端精度丢失
m.addSerializer(Long.class, NumberSerializer.INSTANCE);
m.addSerializer(Long.TYPE, NumberSerializer.INSTANCE);
// LocalDate / LocalTime
m.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE);
m.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE);
m.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE);
m.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE);
// LocalDateTime < - > EpochMillis
m.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE);
m.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
return m;
}
/**
* 初始化全局 JsonUtils直接使用主 ObjectMapper
*/
@Bean
@SuppressWarnings("InstantiationOfUtilityClass")
public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) {
// 1.1 创建 SimpleModule 对象
SimpleModule simpleModule = new SimpleModule();
simpleModule
// 新增 Long 类型序列化规则,数值超过 2^53-1在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型
.addSerializer(Long.class, NumberSerializer.INSTANCE)
.addSerializer(Long.TYPE, NumberSerializer.INSTANCE)
.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE)
.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE)
.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE)
.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE)
// 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳
.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE)
.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE);
// 1.2 注册到 objectMapper
objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule));
// 2. 设置 objectMapper 到 JsonUtils
JsonUtils.init(CollUtil.getFirst(objectMappers));
log.info("[init][初始化 JsonUtils 成功]");
public JsonUtils jsonUtils(ObjectMapper objectMapper) {
JsonUtils.init(objectMapper);
log.debug("[init][初始化 JsonUtils 成功]");
return new JsonUtils();
}

View File

@@ -180,8 +180,7 @@ public class GlobalExceptionHandler {
@ExceptionHandler(HttpMessageNotReadableException.class)
public CommonResult<?> methodArgumentTypeInvalidFormatExceptionHandler(HttpMessageNotReadableException ex) {
log.warn("[methodArgumentTypeInvalidFormatExceptionHandler]", ex);
if (ex.getCause() instanceof InvalidFormatException) {
InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause();
if (ex.getCause() instanceof InvalidFormatException invalidFormatException) {
return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue()));
}
if (StrUtil.startWith(ex.getMessage(), "Required request body is missing")) {

View File

@@ -147,10 +147,9 @@ public class WebFrameworkUtils {
public static HttpServletRequest getRequest() {
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (!(requestAttributes instanceof ServletRequestAttributes)) {
if (!(requestAttributes instanceof ServletRequestAttributes servletRequestAttributes)) {
return null;
}
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
return servletRequestAttributes.getRequest();
}

View File

@@ -166,7 +166,7 @@ public class CouponServiceImpl implements CouponService {
public void invalidateCouponsByAdmin(List<Long> giveCouponIds, Long userId) {
// 循环收回
for (Long couponId : giveCouponIds) {
// couponId为空或0则跳过
// couponId 为空或 0 则跳过
if (null == couponId || couponId <= 0) {
continue;
}

View File

@@ -8,8 +8,8 @@ import com.anji.captcha.service.impl.CaptchaServiceFactory;
import com.anji.captcha.util.AESUtil;
import com.anji.captcha.util.ImageUtils;
import com.anji.captcha.util.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import cn.hutool.core.util.RandomUtil;
import org.apache.commons.lang3.Strings;
import java.awt.*;
import java.awt.geom.AffineTransform;
@@ -82,7 +82,7 @@ public class PictureWordCaptchaServiceImpl extends AbstractCaptchaService {
// 用户输入的验证码(CaptchaVO 中 没有预留字段,暂时用 pointJson 无需加解密)
String userCode = captchaVO.getPointJson();
if (!StringUtils.equalsIgnoreCase(code, userCode)) {
if (!Strings.CI.equals(code, userCode)) {
afterValidateFail(captchaVO);
return ResponseModel.errorMsg(RepCodeEnum.API_CAPTCHA_COORDINATE_ERROR);
}
@@ -209,4 +209,4 @@ public class PictureWordCaptchaServiceImpl extends AbstractCaptchaService {
return RandomUtil.randomString(CHARACTERS, length);
}
}
}

View File

@@ -77,8 +77,8 @@ public class AuthRequestFactory {
extendList = extend.getConfig()
.keySet()
.stream()
.filter(x -> names.contains(x.toUpperCase()))
.map(String::toUpperCase)
.filter(names::contains)
.collect(Collectors.toList());
}
@@ -318,4 +318,4 @@ public class AuthRequestFactory {
.proxy(new Proxy(Proxy.Type.valueOf(proxyConfig.getType()), new InetSocketAddress(proxyConfig.getHostname(), proxyConfig.getPort())))
.build());
}
}
}

View File

@@ -114,12 +114,12 @@ public class AliyunSmsClient extends AbstractSmsClient {
@VisibleForTesting
Integer convertSmsTemplateAuditStatus(Integer templateStatus) {
switch (templateStatus) {
case 0: return SmsTemplateAuditStatusEnum.CHECKING.getStatus();
case 1: return SmsTemplateAuditStatusEnum.SUCCESS.getStatus();
case 2: return SmsTemplateAuditStatusEnum.FAIL.getStatus();
default: throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
}
return switch (templateStatus) {
case 0 -> SmsTemplateAuditStatusEnum.CHECKING.getStatus();
case 1 -> SmsTemplateAuditStatusEnum.SUCCESS.getStatus();
case 2 -> SmsTemplateAuditStatusEnum.FAIL.getStatus();
default -> throw new IllegalArgumentException(String.format("未知审核状态(%d)", templateStatus));
};
}
/**
@@ -153,8 +153,8 @@ public class AliyunSmsClient extends AbstractSmsClient {
StringBuilder canonicalHeaders = new StringBuilder(); // 构造请求头,多个规范化消息头,按照消息头名称(小写)的字符代码顺序以升序排列后拼接在一起
StringBuilder signedHeadersBuilder = new StringBuilder(); // 已签名消息头列表,多个请求头名称(小写)按首字母升序排列并以英文分号(;)分隔
headers.entrySet().stream().filter(entry -> entry.getKey().toLowerCase().startsWith("x-acs-")
|| entry.getKey().equalsIgnoreCase("host")
|| entry.getKey().equalsIgnoreCase("content-type"))
|| "host".equalsIgnoreCase(entry.getKey())
|| "content-type".equalsIgnoreCase(entry.getKey()))
.sorted(Map.Entry.comparingByKey()).forEach(entry -> {
String lowerKey = entry.getKey().toLowerCase();
canonicalHeaders.append(lowerKey).append(":").append(String.valueOf(entry.getValue()).trim()).append("\n");
@@ -189,10 +189,10 @@ public class AliyunSmsClient extends AbstractSmsClient {
@SneakyThrows
private static String percentCode(String str) {
Assert.notNull(str, "str 不能为空");
return URLEncoder.encode(str, StandardCharsets.UTF_8.name())
return URLEncoder.encode(str, StandardCharsets.UTF_8)
.replace("+", "%20") // 加号 "+" 被替换为 "%20"
.replace("*", "%2A") // 星号 "*" 被替换为 "%2A"
.replace("%7E", "~"); // 波浪号 "%7E" 被替换为 "~"
}
}
}