springboot-shior集成,将shior的session保存在redis中,从subject中取数据的时候报错。
java.lang.ClassCastException: class com.test.schedule.api.datamodel.vo.UserVo cannot be cast to class com.test.schedule.api.datamodel.vo.UserVo (com.test.schedule.api.datamodel.vo.UserVo is in unnamed module of loader 'app'; com.test.schedule.api.datamodel.vo.UserVo is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @79df64e8)
很是神器,出现了UserVo不能转换为UserVo的错误,通过百度发现有人遇到过这个问题,大致原因是Spring-boot-devtools热加载的时候使用的类加载器只加载项目中的代码,对于jar中的是jdk的类加载器加载的,由于类加载器不一致,导致类型转换失败。
通过sout将类加载器打出来
public static String getUserId()
{
System.out.println("++++++++++++++++++++++++++++++++++");
System.out.println("UserVo:" + UserVo.class.getClassLoader());
System.out.println("SecurityUtils:" + SecurityUtils.getSubject().getPrincipal().getClass().getClassLoader());
System.out.println("++++++++++++++++++++++++++++++++++");
return ((UserVo) SecurityUtils.getSubject().getPrincipal()).getUserId();
}
控制台输出
++++++++++++++++++++++++++++++++++
UserVo:org.springframework.boot.devtools.restart.classloader.RestartClassLoader@79df64e8
SecurityUtils:jdk.internal.loader.ClassLoaders$AppClassLoader@3d4eac69
++++++++++++++++++++++++++++++++++
两个类加载器不一致。
参考别人解决方案就是在resources目录下面创建META-INF文件夹,然后创建spring-devtools.properties文件,文件加上类似下面的配置:
restart.include.shiro=/shiro-*-[\\w.-]+.jar
执行依旧报错
15:32:29.804 [http-nio-8081-exec-2] [] ERROR o.a.c.c.C.[Tomcat].[localhost].[/test].[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] threw exception
java.lang.ClassCastException: class org.apache.shiro.session.mgt.SimpleSession cannot be cast to class org.apache.shiro.session.Session (org.apache.shiro.session.mgt.SimpleSession is in unnamed module of loader 'app'; org.apache.shiro.session.Session is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @5f40fc46)
at com.test.schedule.api.shiro.RedisSessionDAO.doReadSession(RedisSessionDAO.java:88)
将类加载器信息打印出来
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
System.out.println("Session:" + Session.class.getClassLoader());
System.out.println("CommonCoreUtils:" + CommonCoreUtils.class.getClassLoader());
System.out.println("rsp.getValue():" + CommonCoreUtils.unSerialize(rsp.getValue()).getClass().getClassLoader());
Session session = (Session) CommonCoreUtils.unSerialize(rsp.getValue());
System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
结果
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Session:org.springframework.boot.devtools.restart.classloader.RestartClassLoader@5f40fc46
CommonCoreUtils:jdk.internal.loader.ClassLoaders$AppClassLoader@3d4eac69
rsp.getValue():jdk.internal.loader.ClassLoaders$AppClassLoader@3d4eac69
15:32:29.062 [http-nio-8081-exec-2] [] ERROR o.a.c.c.C.[Tomcat].[localhost].[/test].[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [/dyztask] threw exception [Filtered request failed.] with root cause
java.lang.ClassCastException: class org.apache.shiro.session.mgt.SimpleSession cannot be cast to class org.apache.shiro.session.Session (org.apache.shiro.session.mgt.SimpleSession is in unnamed module of loader 'app'; org.apache.shiro.session.Session is in unnamed module of loader org.springframework.boot.devtools.restart.classloader.RestartClassLoader @5f40fc46)
发现两者类加载器依旧不一致,加入在properties文件中加入自定义jar
restart.include.shiro=/shiro-*-[\\w.-]+.jar
restart.include.commonCustomize=/common-customize-core-[\\w.-]+.jar
程序不在报错,控制输出
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Session:org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2031c49d
CommonCoreUtils:org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2031c49d
rsp.getValue():org.springframework.boot.devtools.restart.classloader.RestartClassLoader@2031c49d
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
参考博客作者写的还是很详细的