今天意外发现一个exception:java.lang.ClassCastException:cn.system.model.User cannot be cast to cn.system.model.User,一个User对象不能转换成另一个User

在shiro的认证类中的代码:

SysUserModel SysUserModel = (SysUserModel)subject.getSession().getAttribute(LOGININFO);
  • 1

右边的方法的返回值明明是Object, 
 
按道理是可以强转类型的,却偏偏报异常,虽然已经解决了bug,但还是需要梳理一下思路,以防以后再次入坑。。。后来才发现这与shiro有关

结合网上总结的答案

方案一:不使用spring-boot-devtools热部署

网上说是ClassLoader类加载器的不同导致的类型转换异常,项目启动时加载项目中的类使用的加载器都是org.springframework.boot.devtools.restart.classloader.RestartClassLoader 
而从shiro session 取出来的对象(从redis中取出经过反序列化)的类加载器都是 
sun.misc.Launcher.AppClassLoader, 
很明显会导致类型转换异常,原来Spring的dev-tools为了实现重新装载class自己实现了一个类加载器,来加载项目中会改变的类,方便重启时将新改动的内容更新进来,其实其中官方文档中是有做说明的:

By default, any open project in your IDE will be loaded using the
“restart” classloader, and any regular .jar file will be loaded using
the “base” classloader. If you work on a multi-module project, and not each module is imported into your IDE, you may need to customize
things. To do this you can create a
META-INF/spring-devtools.properties file.
The spring-devtools.properties file can contain restart.exclude. and
restart.include. prefixed properties. The include elements are items
that should be pulled up into the “restart” classloader, and the
exclude elements are items that should be pushed down into the “base”
classloader. The value of the property is a regex pattern that will be
applied to the classpath.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

所以直接在pom文件中将该devtools的jar包注释即可

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5

方案二:解决方案就是在resources目录下面创建META_INF文件夹,然后创建spring-devtools.properties文件,文件加上类似下面的配置: (应该是可以的,但我不知道使用了貌似没效果,杯具)

restart.exclude.companycommonlibs=/mycorp-common-[\w-]+.jar
restart.include.projectcommon=/mycorp-myproj-[\w-]+.jar
  • 1
  • 2

All property keys must be unique. As long as a property starts with 
restart.include. or restart.exclude. it will be considered. All 
META-INF/spring-devtools.properties from the classpath will be loaded. 
You can package files inside your project, or in the libraries that 
the project consumes.

方案三:直接在代码上修改,效果还可以

Object obj = subject.getSession().getAttribute(LOGININFO);
SysUserModel sysUserModel = new SysUserModel();if(obj instanceof SysUserModel) {sysUserModel = (SysUserModel) obj;} else {sysUserModel = JSON.parseObject(JSON.toJSON(obj).toString(), SysUserModel.class);}return sysUserModel;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

方案四:利用反射获取属性(单纯作为收藏看看)

我使用笨方法解决了,用反射获取属性,自己写了一个属性;
/**
* 用于redis session 使用了 spring devtools 导致的类型转换异常
* @param redisObj
* @return
*/
public static SysUserEntity convertObjToEntity(Object redisObj) {
SysUserEntity sysUserEntity = new SysUserEntity();
sysUserEntity.setUserId(NumberUtils.toLong(ReflectUtils.getFieldValue(redisObj, SysUserEntity.FIELD_USERID)+"",0));
sysUserEntity.setUsername(ReflectUtils.getFieldValue(redisObj, SysUserEntity.FIELD_USERNAME)+"");
sysUserEntity.setPassword(ReflectUtils.getFieldValue(redisObj, SysUserEntity.FIELD_PASSWORD)+"");
sysUserEntity.setEmail(ReflectUtils.getFieldValue(redisObj, SysUserEntity.FIELD_EMAIL)+"");
sysUserEntity.setMobile(ReflectUtils.getFieldValue(redisObj, SysUserEntity.FIELD_MOBILE)+"");
sysUserEntity.setStatus(NumberUtils.toInt(ReflectUtils.getFieldValue(redisObj, SysUserEntity.FIELD_STATUS)+"",0));
sysUserEntity.setCreateUserId(NumberUtils.toLong(ReflectUtils.getFieldValue(redisObj, SysUserEntity.FIELD_CREATEUSERID)+"",0));
Object dateObj = ReflectUtils.getFieldValue(redisObj, SysUserEntity.FIELD_CREATETIME);
sysUserEntity.setCreateTime(dateObj != null ? (Date) dateObj : null);
return sysUserEntity;
}try {user = (SysUserEntity)principals.getPrimaryPrincipal();} catch (Exception e) {user = SysUserEntity.convertObjToEntity(principals.getPrimaryPrincipal());}

文章主要参考: 
【SpringBoot】 整合 Shiro 过程中遇到奇怪的类型转换问题 
devtools导致的类型转换异常折中处理方法

shiro中devtools:java.lang.ClassCastException: cn.model.User cannot be cast to cn.model.User相关推荐

  1. java.lang.ClassCastException:android.widget.Button cannot be cast to android.widget.ImageView

    今天遇到一个错误也不知道怎么回事,上网搜了一下: 出现的问题是:java.lang.ClassCastException:android.widget.Button cannot be cast to ...

  2. shiro缓存管理时报错java.lang.ClassCastException: com.xxx.User cannot be cast to com.xxx.User

    一.异常 java.lang.ClassCastException: com.px.myshiro.domain.User cannot be cast to com.px.myshiro.domai ...

  3. java.lang.ClassCastException: com.xx.User cannot be cast to com.xx.User

    项目使用spring boot1.5.2 集成mybatis通用mapper插件,发现查询方法selectByPrimaryKey 会导致发生异常-- java.lang.ClassCastExcep ...

  4. java.lang.ClassCastException: Dao.Impl.AccountDaoImpl cannot be cast to Dao.AccountDao

    在学习Spring操作数据库是,遇到这个问题原因是实现类没有实现接口 Dao层接口 package Dao;import Pojo.Account;public interface AccountDa ...

  5. java类型转换异常_解决java.lang.ClassCastException的java类型转换异常的问题

    解决java.lang.ClassCastException的java类型转换异常的问题,异常,对象,错误,给大家,会报 解决java.lang.ClassCastException的java类型转换 ...

  6. oracle timestamp约束,java.lang.ClassCastException:oracle.sql.TIMESTAMP不能转换为java.sql.Timestamp...

    我正在处理通过网络流式传输ResultSet的应用程序.我最终使用了CachedRowSetImpl类.但是当我连接到一个Oracle数据库时,我会收到一个这样的错误 java.lang.ClassC ...

  7. java.lang.ClassCastException: cn.tedu.domain.User cannot be cast to java.lang.String

    java.lang.ClassCastException: cn.tedu.domain.User cannot be cast to java.lang.String问题解决 从图中可以看到的map ...

  8. 【坑2】java.lang.ClassCastException: cn.itcast.travel.web.servlet.CheckCodeServlet cannot be cast to ja

    java.lang.ClassCastException: cn.itcast.travel.web.servlet.CheckCodeServlet cannot be cast to javax. ...

  9. java.lang.ClassCastException: cn.hutool.json.JSONObject cannot be cast toXXXX

    java.lang.ClassCastException: cn.hutool.json.JSONObject cannot be cast toXXXX 除了网上常见解决方案以外,也存在另一种可能导 ...

最新文章

  1. phpadmin试用
  2. 【c语言】蓝桥杯基础练习 数列特征
  3. 安卓平台运行python_在 android 上运行 python 的方法
  4. python request-python3的request用法实例
  5. jdbc动态查询语句_Java修行第037天--JDBC技术
  6. 为什么多线程可以利用到多核?
  7. python 内置函数 sum()函数 求和函数
  8. 视频播放器——开源免费三大代表
  9. pvbrowser安装教程(Linux)
  10. MongoDB数据库设计中6条重要的经验法则
  11. 阿里云MVP:如何设计实现一个通用的微服务架构?
  12. 信息学奥赛一本通C++语言——1119:矩阵交换行
  13. mybatis查询出现索引越界异常
  14. python面试题-如“上海 深圳 深圳 上海“,要求输入一个匹配模式,比如: aabb,判断是否符合
  15. 稳定版正式发布 | 用 Flutter 构建 Windows 桌面应用程序
  16. 教你微信怎么加更多好友的绝佳方法
  17. Google Play支付 接入配置
  18. 毕马威计算机测试题,2021年KPMG毕马威笔试含详解.doc
  19. 添加背景音乐(visual stdio2019)
  20. 用Python爬取网易云热门评论(亲测有效)

热门文章

  1. 联想x201i进入pe蓝屏问题
  2. 城市改造 (city)
  3. 电脑音频转换mp3格式怎么操作
  4. 海盗分金币问题 【转载】
  5. 谁是房租暴涨的真正推手?
  6. 简易计算器(只有加法)
  7. Java毕设项目大型商场商品库存信息管理系统(java+VUE+Mybatis+Maven+Mysql)
  8. html空格符nbsp
  9. rcnn 回归_目标检测-从RCNN到Mask RCNN两步检测算法总结-火龙果软件
  10. Android--高德地图通过经纬度简单的实现轨迹回放