我正在尝试使用Jetty服务器运行Jersey REST服务。当我在IntelliJ中运行时,出现以下错误:

java.lang.NoSuchMethodError: javax.ws.rs.core.Application.getProperties()Ljava/util/Map;
    at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:309)
    at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:338)
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:171)
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:363)
    at javax.servlet.GenericServlet.init(GenericServlet.java:244)
    etc...
    at service.WebserviceRunner.start(WebserviceRunner.java:37)

如果我在Eclipse中运行相同的项目,它将运行良好。 IDE为什么会有所作为?

WebserviceRunner.java
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.WebAppContext;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.servlet.ServletContainer;

public class WebserviceRunner {

    private Server server;
    private int port;
    private String host;

    public WebserviceRunner(String host, int port) {
        this.server = new Server(port);
        this.host = host;
        this.port = port;
    }

    public void start() throws Exception {
        HandlerCollection handlers = new HandlerCollection();
        WebAppContext handler = new WebAppContext();

        handler.setContextPath("/");
        handler.setResourceBase("./");
        handler.setClassLoader(Thread.currentThread().getContextClassLoader());

        ServletHolder restServlet = handler.addServlet(ServletContainer.class,  "/*");
        restServlet.setInitOrder(0);
        restServlet.setInitParameter(ServerProperties.PROVIDER_PACKAGES,"resource");

        handlers.addHandler(handler);

        server.setHandler(handlers);
        server.start();
        System.out.println("API started... at 'http://" + getHostAndPort() + "'");
    }

    private String getHostAndPort() {
        return host + ":" + port;
    }

    public static void main(String[] args) throws Exception {
        new WebserviceRunner("localhost", 8315).start();
    }
}

build.gradle
apply plugin: 'java'
apply plugin: 'jetty'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'war'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.glassfish.jersey.core:jersey-server:2.17'
    compile 'org.glassfish.jersey.containers:jersey-container-servlet-core:2.17'

    compile 'org.javassist:javassist:3.15.0-GA'
    compile 'javax.ws.rs:javax.ws.rs-api:2.0.1'
    compile 'javax.inject:javax.inject:1'
    compile 'com.google.code.gson:gson:2.2.2'
    compile 'com.google.guava:guava:10.0'
    compile 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.3.0'
    testCompile group: 'junit', name: 'junit', version: '4.11'

    def jettyVersion = '7.2.2.v20101205';
    compile "org.eclipse.jetty:jetty-server:${jettyVersion}"
    compile "org.eclipse.jetty:jetty-webapp:${jettyVersion}"
    compile "org.eclipse.jetty:jetty-servlet:${jettyVersion}"
    compile "org.eclipse.jetty:jetty-servlets:${jettyVersion}"
    compile "org.eclipse.jetty:jetty-annotations:${jettyVersion}"
    compile 'org.mortbay.jetty:jsp-2.1-glassfish:2.1.v20100127'
    compile 'javax.servlet:jstl:1.2'
    compile 'javax.servlet:javax.servlet-api:3.0.1'
}

注意:我认为这与在我的类路径上具有同一Application类的两个不同版本有关。为什么只导入一个时为什么呢?

最佳答案

昨天,我使用Maven而不是Gradle遇到了这个问题。
没错,问题是由于在同一包中有两个具有相同类名的jar:java.ws.rs.core.Application。

我能够通过搜索依赖关系树并找到哪个jar的依赖关系引入Application的泽西版,并使用Maven的排除标签将其排除,来解决此问题。

在您的情况下,这很明显:类加载器正在查看java.ws.rs.core.Application的两个版本,并从org.glassfish.jersey.core中选择一个版本,而不是您想要的版本。

关于为什么它在Eclipse中而不是在IDEA中起作用的原因,类加载器不能保证类的加载顺序,使用两个不同的类加载器可能会以不同的顺序加载类,并且如果存在重复会导致不同的行为。

10-07 19:03
查看更多