Commit 441fe1872099bab8ac1e999e484ece0b777fa4cf
1 parent
005d64aa
feat:【framework 框架】优化 jackson 的初始化
Showing
3 changed files
with
51 additions
and
25 deletions
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/db/TenantDatabaseInterceptor.java
| ... | ... | @@ -75,7 +75,7 @@ public class TenantDatabaseInterceptor implements TenantLineHandler { |
| 75 | 75 | if (TenantBaseDO.class.isAssignableFrom(tableInfo.getEntityType())) { |
| 76 | 76 | return false; |
| 77 | 77 | } |
| 78 | - // 如果添加了 @TenantIgnore 注解,显然也不忽略租户 | |
| 78 | + // 如果添加了 @TenantIgnore 注解,则忽略租户 | |
| 79 | 79 | TenantIgnore tenantIgnore = tableInfo.getEntityType().getAnnotation(TenantIgnore.class); |
| 80 | 80 | return tenantIgnore != null; |
| 81 | 81 | } | ... | ... |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/jackson/config/YudaoJacksonAutoConfiguration.java
| 1 | 1 | package cn.iocoder.yudao.framework.jackson.config; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.collection.CollUtil; | |
| 4 | 3 | import cn.iocoder.yudao.framework.common.util.json.JsonUtils; |
| 5 | 4 | import cn.iocoder.yudao.framework.common.util.json.databind.NumberSerializer; |
| 6 | 5 | import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeDeserializer; |
| 7 | 6 | import cn.iocoder.yudao.framework.common.util.json.databind.TimestampLocalDateTimeSerializer; |
| 7 | +import com.fasterxml.jackson.databind.Module; | |
| 8 | 8 | import com.fasterxml.jackson.databind.ObjectMapper; |
| 9 | 9 | import com.fasterxml.jackson.databind.module.SimpleModule; |
| 10 | 10 | import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; |
| ... | ... | @@ -13,39 +13,65 @@ import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; |
| 13 | 13 | import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; |
| 14 | 14 | import lombok.extern.slf4j.Slf4j; |
| 15 | 15 | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| 16 | +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; | |
| 17 | +import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; | |
| 16 | 18 | import org.springframework.context.annotation.Bean; |
| 17 | 19 | |
| 18 | 20 | import java.time.LocalDate; |
| 19 | 21 | import java.time.LocalDateTime; |
| 20 | 22 | import java.time.LocalTime; |
| 21 | -import java.util.List; | |
| 22 | 23 | |
| 23 | -@AutoConfiguration | |
| 24 | +@AutoConfiguration(after = JacksonAutoConfiguration.class) | |
| 24 | 25 | @Slf4j |
| 25 | 26 | public class YudaoJacksonAutoConfiguration { |
| 26 | 27 | |
| 28 | + /** | |
| 29 | + * 从 Builder 源头定制(关键:使用 *ByType,避免 handledType 要求) | |
| 30 | + */ | |
| 27 | 31 | @Bean |
| 28 | - @SuppressWarnings("InstantiationOfUtilityClass") | |
| 29 | - public JsonUtils jsonUtils(List<ObjectMapper> objectMappers) { | |
| 30 | - // 1.1 创建 SimpleModule 对象 | |
| 31 | - SimpleModule simpleModule = new SimpleModule(); | |
| 32 | - simpleModule | |
| 33 | - // 新增 Long 类型序列化规则,数值超过 2^53-1,在 JS 会出现精度丢失问题,因此 Long 自动序列化为字符串类型 | |
| 34 | - .addSerializer(Long.class, NumberSerializer.INSTANCE) | |
| 35 | - .addSerializer(Long.TYPE, NumberSerializer.INSTANCE) | |
| 36 | - .addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE) | |
| 37 | - .addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE) | |
| 38 | - .addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE) | |
| 39 | - .addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE) | |
| 40 | - // 新增 LocalDateTime 序列化、反序列化规则,使用 Long 时间戳 | |
| 41 | - .addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE) | |
| 42 | - .addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE); | |
| 43 | - // 1.2 注册到 objectMapper | |
| 44 | - objectMappers.forEach(objectMapper -> objectMapper.registerModule(simpleModule)); | |
| 32 | + public Jackson2ObjectMapperBuilderCustomizer ldtEpochMillisCustomizer() { | |
| 33 | + return builder -> builder | |
| 34 | + // Long -> Number | |
| 35 | + .serializerByType(Long.class, NumberSerializer.INSTANCE) | |
| 36 | + .serializerByType(Long.TYPE, NumberSerializer.INSTANCE) | |
| 37 | + // LocalDate / LocalTime | |
| 38 | + .serializerByType(LocalDate.class, LocalDateSerializer.INSTANCE) | |
| 39 | + .deserializerByType(LocalDate.class, LocalDateDeserializer.INSTANCE) | |
| 40 | + .serializerByType(LocalTime.class, LocalTimeSerializer.INSTANCE) | |
| 41 | + .deserializerByType(LocalTime.class, LocalTimeDeserializer.INSTANCE) | |
| 42 | + // LocalDateTime < - > EpochMillis | |
| 43 | + .serializerByType(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE) | |
| 44 | + .deserializerByType(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE); | |
| 45 | + } | |
| 45 | 46 | |
| 46 | - // 2. 设置 objectMapper 到 JsonUtils | |
| 47 | - JsonUtils.init(CollUtil.getFirst(objectMappers)); | |
| 48 | - log.info("[init][初始化 JsonUtils 成功]"); | |
| 47 | + /** | |
| 48 | + * 以 Bean 形式暴露 Module(Boot 会自动注册到所有 ObjectMapper) | |
| 49 | + */ | |
| 50 | + @Bean | |
| 51 | + public Module timestampSupportModuleBean() { | |
| 52 | + SimpleModule m = new SimpleModule("TimestampSupportModule"); | |
| 53 | + // Long -> Number,避免前端精度丢失 | |
| 54 | + m.addSerializer(Long.class, NumberSerializer.INSTANCE); | |
| 55 | + m.addSerializer(Long.TYPE, NumberSerializer.INSTANCE); | |
| 56 | + // LocalDate / LocalTime | |
| 57 | + m.addSerializer(LocalDate.class, LocalDateSerializer.INSTANCE); | |
| 58 | + m.addDeserializer(LocalDate.class, LocalDateDeserializer.INSTANCE); | |
| 59 | + m.addSerializer(LocalTime.class, LocalTimeSerializer.INSTANCE); | |
| 60 | + m.addDeserializer(LocalTime.class, LocalTimeDeserializer.INSTANCE); | |
| 61 | + // LocalDateTime < - > EpochMillis | |
| 62 | + m.addSerializer(LocalDateTime.class, TimestampLocalDateTimeSerializer.INSTANCE); | |
| 63 | + m.addDeserializer(LocalDateTime.class, TimestampLocalDateTimeDeserializer.INSTANCE); | |
| 64 | + return m; | |
| 65 | + } | |
| 66 | + | |
| 67 | + /** | |
| 68 | + * 初始化全局 JsonUtils,直接使用主 ObjectMapper | |
| 69 | + */ | |
| 70 | + @Bean | |
| 71 | + @SuppressWarnings("InstantiationOfUtilityClass") | |
| 72 | + public JsonUtils jsonUtils(ObjectMapper objectMapper) { | |
| 73 | + JsonUtils.init(objectMapper); | |
| 74 | + log.debug("[init][初始化 JsonUtils 成功]"); | |
| 49 | 75 | return new JsonUtils(); |
| 50 | 76 | } |
| 51 | 77 | ... | ... |
yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
| ... | ... | @@ -166,7 +166,7 @@ public class CouponServiceImpl implements CouponService { |
| 166 | 166 | public void invalidateCouponsByAdmin(List<Long> giveCouponIds, Long userId) { |
| 167 | 167 | // 循环收回 |
| 168 | 168 | for (Long couponId : giveCouponIds) { |
| 169 | - // couponId为空或0则跳过 | |
| 169 | + // couponId 为空或 0 则跳过 | |
| 170 | 170 | if (null == couponId || couponId <= 0) { |
| 171 | 171 | continue; |
| 172 | 172 | } | ... | ... |