我有两个Stream
和Lake
类扩展WaterBody
。 Stream
或Lake
存储在由Apache Shiro 1.2.4管理的会话中,稍后将使用。
WaterBody lake = new Lake();
session.setAttribute("water", lake);`
使用
检索它WaterBody water = (WaterBody) session.getAttribute("water");
在Wildfly 9.0.2服务器重新启动时,我可以将对象存储到会话中,并且可以很好地检索它们。如果我将Lake
或Stream
存储到water
会话属性,则无关紧要。但是,在重新部署项目而不重新启动Wildfly服务器后,我可以将会话属性water
仅存储为与之前相同的类类型,即:首先不能存储Lake
并重新部署然后存储{ {1}}。我收到这个错误:
Stream
类 java.lang.ClassCastException: cannot assign instance of [Lfwp.fish.water.HydroUnit; to field fwp.fish.water.WaterBody.hucs of type [Lfwp.fish.water.HydroUnit; in instance of fwp.fish.water.Stream
包含类型为WaterBody
的私有字段的getter和setter,由于HydroUnit
和Stream
都继承了此错误,因此错误无效。< / p>
如果重新开始,Lake
会话属性在重新部署之前和之后都分配给同一个类,它会将值分配给会话变量,然后在检索时会抛出此错误:< / p>
water
由于java.lang.ClassCastException: fwp.fish.water.Lake cannot be cast to fwp.fish.water.WaterBody
扩展Lake
,因此不应该有问题。
使用Shiro,我们使用ehcache 2.9作为会话缓存。
似乎缓存忽略了WaterBody
,或者它在幕后生成了一个不同的缓存,它认为当它们没有重新部署之间时,类已经改变了。
课程:
serialVersionUID
答案 0 :(得分:1)
在研究了这个问题后,我们发现了这一点。当项目运行时,ClassLoader
第一次在使用它们时创建类,然后将对象存储到会话中。在服务器运行时对该项目进行热重新部署后,当再次加载Class
时,ClassLoader
会创建该Class
的新实例。但是,会话仍会记住上次Class
的对象存储时的Class
,有时会让新对象存储在会话中,并显示为同一个对象。但是在检索对象时,它仍然由Class
的旧实例定义,因此当尝试将其强制转换为Class
的当前实例时,它将失败。
我们的解决方案是,在会话中存储对象的项目是将将作为会话中的对象存储的类分离为正在重新部署的项目所包含的单独.jar
模块。这样,如果Class
文件发生更改,则无论如何都必须重新启动服务器,因为模块依赖关系已发生更改。现在,如果项目是热重新部署的,那么这些类保持不变,因为它们不在正在刷新的.war
文件中。