spring boot從redis取快取發生java.lang.ClassCastException異常
目錄樹
- 異常日誌資訊
- 錯誤原因
- 解決方法
異常日誌資訊
1 2018-09-24 15:26:03.406 ERROR 13704 --- [nio-8888-exec-8] o.a.c.c.C.[.[.[/].[dispatcherServlet]: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: com.winds.admin.core.model.system.User cannot be cast to com.winds.admin.core.model.system.User] with root cause 2 3 java.lang.ClassCastException: com.winds.admin.core.model.system.User cannot be cast to com.winds.admin.core.model.system.User 4at com.winds.admin.utils.web.WebValidateUtil.isLogin(WebValidateUtil.java:70) ~[classes/:na] 5at com.winds.admin.web.controller.HelloController.login(HelloController.java:45) ~[classes/:na] 6at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_51] 7at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_51] 8at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_51] 9at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_51] 10at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.19.RELEASE.jar:4.3.19.RELEASE] 11at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.19.RELEASE.jar:4.3.19.RELEASE] 12at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.19.RELEASE.jar:4.3.19.RELEASE] 13at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:849) ~[spring-webmvc-4.3.19.RELEASE.jar:4.3.19.RELEASE] 14at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:760) ~[spring-webmvc-4.3.19.RELEASE.jar:4.3.19.RELEASE] 15at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.19.RELEASE.jar:4.3.19.RELEASE] 16at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.19.RELEASE.jar:4.3.19.RELEASE] 17at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.19.RELEASE.jar:4.3.19.RELEASE] 18at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.19.RELEASE.jar:4.3.19.RELEASE] 19at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.19.RELEASE.jar:4.3.19.RELEASE] 20at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.34.jar:8.5.34] 21at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.19.RELEASE.jar:4.3.19.RELEASE] 22at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.34.jar:8.5.34] 23at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.34.jar:8.5.34] 24at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34] 25at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.34.jar:8.5.34] 26at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.34.jar:8.5.34] 27at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
錯誤原因
仔細看你會發現這個類轉換異常很奇怪,為什麼呢?我們注意到這兩個User不管是包名還是類名是完全一樣的[ java.lang.ClassCastException : com.winds.admin.core.model.system.User cannot be cast to com.winds.admin.core.model.system.User ],但也發生了強制轉換異常,那麼還有什麼原因會引起這種情況呢?那就只有一種情況了:使用的類載入器不一樣。主要原因是pom檔案中引入了DevTools配置。 當你使用DevTools進行快取時,需要了解這一限制。 當物件序列化到快取中時,應用程式類載入器是C1。然後,更改一些程式碼或者配置後,devtools會自動重新啟動上下文並建立一個新的類載入器C2。所以當你通過redis操作獲取快取反序列化的時候應用的類載入器是C2,雖然包名及其來類名完全一致,但是序列化與反序列化是通過不同的類載入器載入則在JVM中它們也不是同一個類。如果快取庫沒有考慮上下文類載入器,那麼這個物件會附加錯誤的類載入器 ,也就是我們常見的類強制轉換異常(ClassCastException)。
這個問題可參見:Stack OverFlow的ofollow,noindex">文章 。
解決方法
將devtools熱部署註釋掉:
<!-- 熱部署模組 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>