java - 类加载器和与 Apache Tomcat 共享 .jar 文件

标签 java tomcat classloader

如果我有需要在我的 webapp 和 Tomcat 之间共享的类(例如自定义领域和主体),包含这些类的 .jar 文件应该放在哪里?

目前我将 .jar 放在 ${CATALINA_HOME}/lib 中。当从相同类型的类分配引用时,此结果是 ClassCastException。这是一个例子:

MyCustomPrincipal principal = (MyCustomPrincipal)FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();

上述方法抛出 ClassCastException。该方法返回一个实际的 MyCustomPrincipal 类型(因为这是我的自定义领域在执行身份验证时赋予 Tomcat 的类型),显然,它是由不同的类加载器创建的。我该如何解决这个问题,以便 Tomcat 和我的 Web 应用程序都可以使用 MyCustomPrincipal?

http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html

感谢任何帮助。 安德鲁

最佳答案

看起来您加载了 2 个副本,一次在 tomcat 中,一次在您的 WEB-INF/lib jar 或已部署应用程序的其他类路径中。

您获得类路径异常的原因在于 WAR 查找类的方式。与普通的 Java 规则相反,war 首先在 war 内部查找一个类,然后才将请求传递给父类加载器。

一个类的标识依赖于类加载器,在一个类加载器中加载的同一个类在另一个类加载器中转换时会产生类转换异常。

解决方案是确保war 不包含应由容器提供的类。如果您使用 Maven,您可以将这些依赖项标记为“已提供”,如果您使用 Ant,则必须将类路径列表分成 2 部分并针对两者进行编译,但仅使用构建 war 所需的那些。

关于java - 类加载器和与 Apache Tomcat 共享 .jar 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3076959/

相关文章:

java - 有没有办法从 Java 中的键盘获取所有键?

Java 自定义类加载器

java - grails war 部署错误

java - 如何在运行时在 Tomcat 中创建一个 hibernate.properties 文件

java - 错误无法检测 ServletContainerInitializers Tomcat 8

java - 为什么我的类(class)没有加载

java - 通过 onejar 插件使用反射

java - 运行springboot应用程序的 "gradle bootRun"和 "gradle run"有什么区别?

java错误两种方法对泛型有相同的删除

java - 从 Android 应用程序向 Web 托管的 Java 应用程序发送和接收数据