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

And*_*rew 3 java tomcat classloader

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

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

MyCustomPrincipal principal = (MyCustomPrincipal)FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal();
Run Code Online (Sandbox Code Playgroud)

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

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

任何帮助表示赞赏。安德鲁

Pet*_*ans 5

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

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

一个类的身份依赖于类加载器,并且在 1 个类加载器中加载的同一个类在另一个类加载器中被转换时会产生一个类转换异常。

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