java.lang.NoSuchMethodError 因为 Tomcat 的 lib 文件夹中有重复的 class

java.lang.NoSuchMethodError because of duplicate class available in lib folder of Tomcat

我正面临

java.lang.NoSuchMethodError:javax.persistence.PersistenceContext.synchronization()Ljavax/persistence/SynchronizationType

在 Tomcat 8 中部署我的应用程序时,因为 tomcat class 加载程序正在从位于 [=35] 的注释-api.jar 文件加载 PersistenceContext class =] 文件夹和 PersistenceContext class from annotations-api.jar 不包含同步方法如下

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 class 我已经复制到 TOMCAT_HOME\lib 文件夹而不是注释-api.jar 存在于 TOMCAT_HOME\lib 文件夹中,因为来自 javax.persitence-api-2.2 jar 的 PersistenceContext class 包含如下同步方法

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- 加载 PersistenceContext class 2.2.jar代替注解-api.jar ?

编辑:Tomcat 8 lib 文件夹已经包含注释-api.jar 并且我已经在 lib 文件夹中复制了 javax.persistence-api-2.2.jar Tomcat 在 Tomcat 8 中支持 eclipselink,因此我的 dependencies.gradle 中的 exclude annotations-api.jar 选项不会有帮助,因为 annotations-api.jar 已经是Tomcat 的 lib 文件夹。我没有自己加注解-api.jar

注意:相同的应用程序是 Tomcat 9 中的 运行 文件,因为 Tomcat 9 中的注释-api.jar 不包含 javax.persistence 包。

尝试将 javax.persistence-api-2.2.jar 添加为项目的依赖项并将其从 tomcat 库中删除,原因是 /WEB-INF/lib/* 如果 Web 应用程序 class 加载程序未配置 delegate="true

,则将首先加载 Web 应用程序的 .jar

正常顺序:

  1. Bootstrap class 你的 JVM(核心 java classes)
  2. 您的 Web 应用程序
  3. /WEB-INF/classes
  4. /WEB-INF/lib/*.jar 你的网络应用程序
  5. 系统 class 加载程序 classes(Tomcat / 类路径特定 classes)
  6. 通用 class 加载器 classes(classes 对所有网络应用程序通用)

使用 delegate="true" 然后命令:

  1. Bootstrap class 你的 JVM(核心 java classes)
  2. 系统 class 加载程序 classes(Tomcat / 类路径特定 classes)
  3. 通用 class 加载器 classes(classes 对所有网络应用程序通用)
  4. 您的 Web 应用程序
  5. /WEB-INF/classes
  6. /WEB-INF/lib/*.jar 你的网络应用程序