Blade 3.0.0 LocalDateTime Redis序列化失败

Blade 未结 1 582
klniu
klniu 剑圣 2022-07-27 09:50

一、该问题的重现步骤是什么?

现在使用CacheUtil.get时会报以下错误,该字段是一个LocalDateTime字段:

org.springframework.data.redis.serializer.SerializationException: Could not write JSON: Type id handling not implemented for type java.lang.Object (by serializer of type com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer) (through reference chain: cn.safetyline.base.entity.SoftwareVersion["publishDatetime"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Type id handling not implemented for type java.lang.Object (by serializer of type com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer) (through reference chain: cn.safetyline.base.entity.SoftwareVersion["publishDatetime"])
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.serialize(GenericJackson2JsonRedisSerializer.java:125)
at org.springframework.data.redis.serializer.DefaultRedisElementWriter.write(DefaultRedisElementWriter.java:44)
at org.springframework.data.redis.serializer.RedisSerializationContext$SerializationPair.write(RedisSerializationContext.java:287)
at org.springframework.data.redis.cache.RedisCache.serializeCacheValue(RedisCache.java:282)
at org.springframework.data.redis.cache.RedisCache.put(RedisCache.java:168)
at org.springblade.core.cache.utils.CacheUtil.get(CacheUtil.java:219)
at org.springblade.core.cache.utils.CacheUtil.get(CacheUtil.java:190)
at cn.safetyline.base.cache.SoftwareVersionCache.getAndroidLatestVersion(SoftwareVersionCache.kt:18)
at cn.safetyline.base.controller.SoftwareVersionController.getAndroidLatestVersion(SoftwareVersionController.kt:107)
at cn.safetyline.base.controller.SoftwareVersionController$$FastClassBySpringCGLIB$$b3fdc033.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89)
at org.springblade.core.log.aspect.RequestLogAspect.aroundApi(RequestLogAspect.java:112)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:634)
at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:624)
at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:72)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708)
at cn.safetyline.base.controller.SoftwareVersionController$$EnhancerBySpringCGLIB$$89dcdeee.getAndroidLatestVersion(<generated>)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)


我Redis使用的是默认的ProtoStuffy序列化方式,在blade-starter-redis包中,redisSerializer使用的是以下这个

	/**
* 默认的序列化方式
*
* @param properties 配置
* @return RedisSerializer
*/
default RedisSerializer<Object> defaultRedisSerializer(BladeRedisProperties properties) {
BladeRedisProperties.SerializerType serializerType = properties.getSerializerType();
if (BladeRedisProperties.SerializerType.JDK == serializerType) {
/**
* SpringBoot扩展了ClassLoader,进行分离打包的时候,使用到JdkSerializationRedisSerializer的地方
* 会因为ClassLoader的不同导致加载不到Class
* 指定使用项目的ClassLoader
*
* JdkSerializationRedisSerializer默认使用{@link sun.misc.Launcher.AppClassLoader}
* SpringBoot默认使用{@link org.springframework.boot.loader.LaunchedURLClassLoader}
*/
ClassLoader classLoader = this.getClass().getClassLoader();
return new JdkSerializationRedisSerializer(classLoader);
}
return new GenericJackson2JsonRedisSerializer(TYPE_NAME);
}

在GenericJackson2JsonRedisSerializer中是直接new ObjectMapper()的并没有加载LocalDateTime的module


在升级到3.0.0之前(2.9.1),相同的代码,序列化是没有问题的


根据网上的教程可能是需要实现GenericJackson2JsonRedisSerializer,在其中注入jsr-310的module。但之前的代码没有问题,而且我看blade-starter-redis这次并没有更新什么,不知道是不是Spring升级的原因,请问这个地方是我遗漏了什么吗


二、你期待的结果是什么?实际看到的又是什么?


三、你正在使用的是什么产品,什么版本?在什么操作系统上?

BladeX 3.0.0


四、请提供详细的错误堆栈信息,这很重要。


五、若有更多详细信息,请在下面提供。

1条回答
  • 2022-07-27 23:02

    也许是spring大版本更新后底层逻辑改了,我们后续调试查一下原因,请先用Date类代替吧

    作者追问:2022-07-28 08:15

    多谢翼总,昨天晚上找到原因了,是因为自动装置顺序的事情,ProtoStuffSerializerConfiguration没有在RedisTemplateConfiguration之前初始化,原因是我使用了@ComponenScan的问题,我在@ComponentScan中加了以下内容,好用了

    @ComponentScan("org.springblade", "com.example",
        excludeFilters = [ComponentScan.Filter(type = FilterType.REGEX, pattern = ["org.springblade.core.redis.config.*"])]
    )


    0 讨论(0)
提交回复