java - java.lang.NoSuchMethodError 因为 Tomcat 的 lib 文件夹中有重复的类
问题描述
我面对
java.lang.NoSuchMethodError:javax.persistence.PersistenceContext.synchronization()Ljavax/persistence/SynchronizationType
在 Tomcat 8 中部署我的应用程序时,因为 tomcat 类加载器正在从位于 TOMCAT_HOME\lib 文件夹的 annotations-api.jar 文件中加载 PersistenceContext 类,而 annotations-api.jar 中的 PersistenceContext 类不包含如下同步方法
package javax.persistence;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PersistenceContext {
String name() default "";
String unitName() default "";
PersistenceContextType type() default PersistenceContextType.TRANSACTION;
PersistenceProperty[] properties() default {};
}
虽然我希望 tomcat 从 javax.persitence-api-2.2 jar 加载 PersistenceContext 类,但我已将其复制到 TOMCAT_HOME\lib 文件夹而不是 TOMCAT_HOME\lib 文件夹中的 annotations-api.jar,因为来自 javax.persitence-api-2.2 的 PersistenceContext 类jar包含同步方法如下
package javax.persistence;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Repeatable(PersistenceContexts.class)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface PersistenceContext {
String name() default "";
String unitName() default "";
PersistenceContextType type() default PersistenceContextType.TRANSACTION;
SynchronizationType synchronization() default SynchronizationType.SYNCHRONIZED;
PersistenceProperty[] properties() default {};
}
这样tomcat 在部署我的应用程序时不会给出java.lang.NoSuchMethodError: javax.persistence.PersistenceContext.synchronization()Ljavax/persistence/SynchronizationType 。
如何在 Tomcat 8 中给予优先权,以便 Tomcat 8 从 javax.persistence-api-2.2.jar 而不是 annotations-api.jar 加载 PersistenceContext 类?
编辑:Tomcat 8 lib 文件夹已经包含 annotations-api.jar 并且我已经将 javax.persistence-api-2.2.jar 复制到 Tomcat 的 lib 文件夹中,以便在 Tomcat 8 中支持 eclipselink,因此在我的 dependencies.gradle 中排除 annotations-api.jar 选项不会有帮助,因为 annotations-api.jar 已经是 Tomcat 的 lib 文件夹的一部分。我还没有自己添加 annotations-api.jar。
注意:同一应用程序正在 Tomcat 9 中运行文件,因为 Tomcat 9 中的 annotations-api.jar 不包含 javax.persistence 包。
解决方案
尝试在项目中添加 javax.persistence-api-2.2.jar 作为依赖项并将其从 tomcat lib 中删除,原因是如果 web 应用程序的 /WEB-INF/lib/*.jar 将首先加载应用程序类加载器未配置为 delegate="true
正常顺序:
- JVM 的引导类(核心 java 类)
- /WEB-INF/Web 应用程序的类
- /WEB-INF/lib/*.jar 您的 Web 应用程序
- 系统类加载器类(Tomcat / Classpath 特定类)
- 通用类加载器类(所有 Web 应用程序通用的类)
使用delegate="true " 然后订购:
- JVM 的引导类(核心 java 类)
- 系统类加载器类(Tomcat / Classpath 特定类)
- 通用类加载器类(所有 Web 应用程序通用的类)
- /WEB-INF/Web 应用程序的类
- /WEB-INF/lib/*.jar 您的 Web 应用程序
推荐阅读
- angular - Angular Material 7 使用带有拖放功能的网格
- hyperledger-fabric - Hyperledger Fabric CA:我们在哪里可以找到环境变量列表?
- javascript - 缩小 Vuejs App 导致浏览器崩溃
- c# - 我无法发布 ASP.NET 项目,即使我可以构建它
- android - Android通知栏自定义内容未显示
- ms-access - 在 MS Access 的列中标记损坏的超链接
- vue.js - 无法覆盖 vuetify 中的样式
- docker - Kubernetes Pod 问题
- c# - asp.net c# 类中的无效令牌“for”,生成随机码
- user-interface - 使用 PyQt 和 Panda3D 创建应用程序逻辑