我有两个不同的网络应用程序,每个应用程序都使用不同的类加载器加载相同的 A 类。当我将一个实例放入会话中,然后从另一个 web 应用程序中获取它时,ClassCastException
会抛出 a。
例如,在 webapp A 中,我存储a
在会话中,然后在 webapp B 中,我a
从会话中获取并将其转换为 A,然后ClassCastException
抛出。
有没有办法解决这个问题?
我有两个不同的网络应用程序,每个应用程序都使用不同的类加载器加载相同的 A 类。当我将一个实例放入会话中,然后从另一个 web 应用程序中获取它时,ClassCastException
会抛出 a。
例如,在 webapp A 中,我存储a
在会话中,然后在 webapp B 中,我a
从会话中获取并将其转换为 A,然后ClassCastException
抛出。
有没有办法解决这个问题?
有没有办法解决这个问题?
基本上没有。
就 JLS 而言,类型是不同的类型,JVM 不会允许您假装其他类型。例如,这些类可能有不同的代码和不同的对象布局。如果您可以欺骗 JVM 将类型视为相同,您将能够吹走 JVM 运行时安全性。那就是精神错乱。
解决方案是确保您没有两个不同的类加载器加载同一个类。在 Tomcat 的上下文中,这意味着如果两个或多个 webapps 需要共享一个类的实例,那么该类必须在两者都通用的类加载器中定义;例如,将 JAR 文件放在$CATALINA_HOME/lib
or$CATALINA_HOME/common
目录中。
如果由于技术原因必须由不同的类加载器加载类(可能是因为类确实不同),那么您可以通过定义两个版本的类都实现的接口来解决该问题,然后编程到接口而不是实现类。当然,接口需要由共享类加载器加载……否则你会再次遇到同样的问题。
基本上,您应该避免这种情况 - 要么将这两种功能放在同一个 webapp 中,要么将包含类 A 的库移动到适当的位置,以便只使用一个类加载器。由不同类加载器加载的两个类在 JVM 中是完全不同的——您根本无法在它们之间进行转换。
有关使用的各种类加载器的更多详细信息,请参阅Tomcat 类加载器文档。看起来您希望将此公共类放入公共类加载器区域。正如文档所述,这很不寻常,但如果你真的想在两个 web 应用程序之间共享一个对象(这也很不寻常),这可能是最简单的方法。
你不能。不同类加载器加载的两个类是不同的。
也许您可以序列化共享对象?
我不一定提倡这种方法,但是这就是序列化本质上所做的——你从一些 JVM 或 ClassLoader X序列化并将其加载(反序列化)到另一个 JVM/ClassLoader Y ...
即使类具有相同的包名称和签名,您也不能从不同的类中转换两个对象,但是您可以简单地使用 apache bean utils 库将数据从一个复制到另一个,BeanUtils.copyProperties(o1, o2);