欢迎光临
我们一直在努力

Redis缓存Java对象使用Fastjson序列化Json字符串报ClassCastException

    项目基础框架为:springboot2.x,mybatis(redis作为二级缓存)    

    出现问题是:当第一次查询时,正常返回json数据。当从redis加载数据时报错ClassCastException。以下是异常堆栈:

2019-04-09 11:09:10 [XNIO-1 task-25] [DEBUG] [com.cmgplex.smartjob.baseapi.mapper.sync.ITSyncDepartmentMapper]  - Cache Hit Ratio [com.cmgplex.smartjob.baseapi.mapper.sync.ITSyncDepartmentMapper]: 0.9090909090909091
java.lang.ClassCastException: com.cmgplex.smartjob.voes.sync.TSyncDepartmentVo cannot be cast to com.cmgplex.smartjob.voes.sync.TSyncDepartmentVo
 at com.alibaba.fastjson.serializer.ASMSerializer_4_TSyncDepartmentVo.write(Unknown Source)
 at com.alibaba.fastjson.serializer.ListSerializer.write(ListSerializer.java:137)
 at com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:280)
 at com.alibaba.fastjson.JSON.toJSONString(JSON.java:673)
 at com.alibaba.fastjson.JSON.toJSONString(JSON.java:611)
 at com.alibaba.fastjson.JSON.toJSONString(JSON.java:576)
 at com.cmgplex.smartjob.baseapi.controller.sync.DepartmentController.queryDepartmentVo(DepartmentController.java:45)
 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:189)
 at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
 at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
 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:800)
 at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
 at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
 at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
 at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
 at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:908)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:665)
 at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
 at javax.servlet.http.HttpServlet.service(HttpServlet.java:750)
 at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
 at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
 at org.springframework.boot.actuate.web.trace.servlet.HttpTraceFilter.doFilterInternal(HttpTraceFilter.java:90)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
 at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
 at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
 at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
 at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
 at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
 at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
 at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
 at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
 at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
 at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
 at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
 at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:117)
 at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:106)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
 at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
 at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
 at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200)
 at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
 at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
 at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
 at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
 at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
 at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
 at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
 at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
 at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
 at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
 at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
 at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
 at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
 at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
 at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
 at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
 at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
 at io.undertow.servlet.handlers.SessionRestoringHandler.handleRequest(SessionRestoringHandler.java:119)
 at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
 at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
 at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
 at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
 at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
 at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
 at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
 at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
 at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
 at io.undertow.server.Connectors.executeRootHandler(Connectors.java:364)
 at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
 at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
 at java.lang.Thread.run(Thread.java:748)

    根据堆栈提示,推测是类加载器的问题。因为包名类名完全一致,却报类型转化异常,很明显可能是redis反序列化的对象和json序列化的对象不是同一个类加载器加载出来的。

    一番谷歌百度后,发现是因为我添加了spring-boot-devtools依赖。

    spring-boot-devtools可以实现修改代码或页面后立即重启达到热部署的目的,从而避免springboot每次修改页面或代码必须手动重启的繁琐操作。但也正因为使用了他,每次热部署的时候,他使用自己的类加载器去刷新项目代码,且不刷新依赖jar,而我的json转化对象恰好在jar里,由另外一个类加载器加载,这样就形成了同一个类,不同加载器加载的情况。

    解决办法是去掉spring-boot-devtools依赖,在application.properties增加一行配置

#修改jsp后立即刷新,以下配置适用boot2.x,低版本使用server.jsp-servlet.init-parameters.development=true
server.servlet.jsp.init-parameters.development=true

    注:如果使用的Eclipse代码会自动热部署

    以下是无意发现的一篇非常详细介绍这个问题的链接:https://juejin.im/entry/5ab78cdb518825558359353c

未经允许不得转载:ITyet » Redis缓存Java对象使用Fastjson序列化Json字符串报ClassCastException

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
打开看板娘