Article directory
-
- Environment | Environment
- Error log | Error log
- Cause Analysis | Analysis
-
- org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
- org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
- org.springframework.core.serializer.support.SerializingConverter
- org.springframework.core.serializer.DefaultSerializer
- Solution | Solution
Talk is cheap, show me the code.
Environment | Environment
k | version |
---|---|
OS | windows 10 |
jdk | 1.8 |
Spring Boot | 2.3. 4.RELEASE |
Error log | Error log
2023-09-15 12:08:33.513 ERROR [http-nio-8080-exec-8] c.i.c.c.GlobalExceptionHandler.handleException(GlobalExceptionHandler.java:88): Error message: Canserialize; nested exception is org.springframework.core .serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.itplh.model.dashboard.QueryDashboardResponseDTO] org.springframework.data.redis.serializer.SerializationException: Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.itplh.model.dashboard.QueryDashboardResponseDTO] at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:96) at org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:185) at org.springframework.data.redis.core.DefaultHashOperations.putIfAbsent(DefaultHashOperations.java:206) at com.itplh.biz.dashboard.impl.DashboardCachingRedisImpl.putIfAbsent(DashboardCachingRedisImpl.java:33) at com.itplh.biz.dashboard.AbstractDashboardDataService.dashboardData(AbstractDashboardDataService.java:70) at com.itplh.web.dashboard.DashboardController.queryDashboardDataByCondition(DashboardController.java:91) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:124) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:143) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:374) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:748) Caused by: org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.itplh.model.dashboard .QueryDashboardResponseDTO] at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:64) at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:33) at org.springframework.data.redis.serializer.JdkSerializationRedisSerializer.serialize(JdkSerializationRedisSerializer.java:94) ... 58 common frames omitted Caused by: java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.itplh.model.dashboard.QueryDashboardResponseDTO] at org.springframework.core.serializer.DefaultSerializer.serialize(DefaultSerializer.java:43) at org.springframework.core.serializer.Serializer.serializeToByteArray(Serializer.java:56) at org.springframework.core.serializer.support.SerializingConverter.convert(SerializingConverter.java:60) ... 60 common frames omitted
Cause Analysis | Analysis
The value serializer of RedisTemplate automatically assembled by Spring Boot, the default is JdkSerializationRedisSerializer.
Because the com.itplh.model.dashboard.QueryDashboardResponseDTO
here does not implement the java.io.Serializable
interface.
So when calling DashboardCachingRedisImpl.putIfAbsent
, an exception SerializationException
occurred when serializing value
The source code is as follows.
org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration
private org.springframework.data.redis.cache.RedisCacheConfiguration createConfiguration( CacheProperties cacheProperties, ClassLoader classLoader) {<!-- --> Redis redisProperties = cacheProperties.getRedis(); org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration .defaultCacheConfig(); config = config.serializeValuesWith( SerializationPair.fromSerializer(new JdkSerializationRedisSerializer(classLoader))); // ... return config; }
org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
public JdkSerializationRedisSerializer(@Nullable ClassLoader classLoader) {<!-- --> this(new SerializingConverter(), new DeserializingConverter(classLoader)); }
org.springframework.core.serializer.support.SerializingConverter
public SerializingConverter() {<!-- --> this.serializer = new DefaultSerializer(); }
org.springframework.core.serializer.DefaultSerializer
public class DefaultSerializer implements Serializer<Object> {<!-- --> /** * Writes the source object to an output stream using Java serialization. * The source object must implement {@link Serializable}. * @see ObjectOutputStream#writeObject(Object) */ @Override public void serialize(Object object, OutputStream outputStream) throws IOException {<!-- --> if (!(object instanceof Serializable)) {<!-- --> throw new IllegalArgumentException(getClass().getSimpleName() + " requires a Serializable payload " + "but received an object of type [" + object.getClass().getName() + "]"); } ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream); objectOutputStream.writeObject(object); objectOutputStream.flush(); } }
Solution | Solution
import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; @Configuration public class RedisConfiguration {<!-- --> @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {<!-- --> RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(factory); // jackson2JsonRedisSerializer Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper om = new ObjectMapper(); om.setVisibility(PropertyAccessor.ALL, Visibility.ANY); om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); jackson2JsonRedisSerializer.setObjectMapper(om); // stringRedisSerializer StringRedisSerializer stringRedisSerializer = new StringRedisSerializer(); //The key serialization method adopts the String serialization method. redisTemplate.setKeySerializer(stringRedisSerializer); //The value serialization method uses jackson redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); // The hash key adopts String serialization method redisTemplate.setHashKeySerializer(stringRedisSerializer); // The value serialization method of hash uses Jackson redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } }