无法使用 servlet 3 可插入功能将 Jersey 2.16 集成到 Tomcat 8.0.12

Cannot integrate Jersey 2.16 into Tomcat 8.0.12 using servlet 3 plugability feature

在新项目中,我决定使用带有 Tomcat 8 的最新 Jersey (2.16),但是文档中描述的集成方案导致 Tomcat 抛出 NPE:

java.lang.NullPointerException
org.apache.catalina.loader.WebappClassLoader.binaryNameToPath(WebappClassLoader.java:2503)
org.apache.catalina.loader.WebappClassLoader.findLoadedClass0(WebappClassLoader.java:2708)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1215)
org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1173)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:493)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:534)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1081)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658)
org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:277)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2381)
org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2370)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:744)

这是我的web.xml

<servlet>
    <servlet-name>bla.bla.core.jersey.config.JerseyServerConfig</servlet-name>
</servlet>
<servlet-mapping>
    <servlet-name>bla.bla.core.jersey.config.JerseyServerConfig</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

这是 JerseyServerConfig 的清单:

package ru.huawei.rnd.bulksms.core.jersey.config;

import org.glassfish.jersey.server.ResourceConfig;
import ru.huawei.rnd.bulksms.core.jersey.constants.FILTERS_AND_INTERCEPTORS;
import ru.huawei.rnd.bulksms.core.jersey.constants.JERSEY_FEATURES;

public class JerseyServerConfig extends ResourceConfig {

    public JerseyServerConfig() {
        register(JERSEY_FEATURES.FORM_PROVIDER);
        register(JERSEY_FEATURES.MULTIPART);
        register(FILTERS_AND_INTERCEPTORS.USER_GZIP_FILTER);
        register(FILTERS_AND_INTERCEPTORS.GZIP_ENCODER);
        packages("bla.bla.rest");
    }

}

因此,根据“4.7.2.2. 使用 web.xml 描述符进行部署”中 here 描述的方案,它看起来是正确的。但是当我尝试调用任何 JAX-RS 资源时,砰的一声,Tomcat 抛出 NPE。似乎是因为 web.xml.

中缺少 servlet-class 元素

看来您正在使用 jersey-container-servlet-core dependency. This will work in situations when we declare the servlet container. But when we want to take advantage of the features where Jersey is automatically loaded, we need the jersey-container-servlet

<dependency>
    <groupId>org.glassfish.jersey.containers</groupId>
    <artifactId>jersey-container-servlet</artifactId>
    <version>${jersey.version}</version>
</dependency>

此工件具有 JerseyServletContainerInitializer, which implements SerlvetContainerInitializer(对于 Servlet 3.x 部署)。

在使用前者时测试并得到与您相同的结果,并且在使用后者时工作正常。