为啥在启动 REST 服务时添加注解 FormDataParam 会引发异常?

Posted

技术标签:

【中文标题】为啥在启动 REST 服务时添加注解 FormDataParam 会引发异常?【英文标题】:Why does adding an annotation FormDataParam raise an exception when starting a REST service?为什么在启动 REST 服务时添加注解 FormDataParam 会引发异常? 【发布时间】:2020-04-02 04:47:26 【问题描述】:

Jersey documentation(版本 2.29.1)具有以下示例(Example 9.50. Use of @FormDataParam annotation):

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
public String postForm(
    @DefaultValue("true") @FormDataParam("enabled") boolean enabled,
    @FormDataParam("data") FileData bean,
    @FormDataParam("file") InputStream file,
    @FormDataParam("file") FormDataContentDisposition fileDisposition) 

    // ...

就我而言,方法如下:

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/test")
public Response saveFiles(        
    @FormDataParam("file") InputStream file,
    @FormDataParam("file") FormDataContentDisposition fileDisposition
)
    return Response.ok().build();

当服务器启动时(也就是说,它甚至没有到达方法调用),我得到以下错误(使用 Apache Tomcat / 8.5.16):

键入异常报告

servlet [rest.ApplicationConfig] 的消息 Servlet.init() 抛出 异常

描述 服务器遇到了一个意外情况 阻止它完成请求。

例外

javax.servlet.ServletException: Servlet.init() 用于 servlet [rest.ApplicationConfig] 抛出异常 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 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:748)

根本原因

java.lang.IllegalStateException: 资源配置不正确 在这种情况下可以修改。 org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:246) org.glassfish.jersey.server.ResourceConfig$ImmutableState.register(ResourceConfig.java:193) org.glassfish.jersey.server.ResourceConfig.register(ResourceConfig.java:426) org.glassfish.jersey.servlet.WebComponent.(WebComponent.java:306) org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154) org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:346) javax.servlet.GenericServlet.init(GenericServlet.java:158) org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624) org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) 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:748)

注意根本原因的完整堆栈跟踪在服务器中可用 日志。

另外,如果去掉@FormDataParam (" file ") InputStream file@FormDataParam ("file") FormDataContentDisposition fileDisposition,那么服务器正常启动:

@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Path("/test")
public Response saveFiles()
    return Response.ok().build();

服务器本身的配置不使用 web.xml,如果这很重要的话:

@ApplicationPath("/")
public class ApplicationConfig extends Application 


这样试了一下,结果一模一样:

@ApplicationPath("/")
public class ApplicationConfig extends ResourceConfig 
    public ApplicationConfig()            
        register(MultiPartFeature.class);
    

问题是什么以及如何解决?

【问题讨论】:

【参考方案1】:

确实,问题出在ApplicationConfig 类中。 首先,该类在rest 包中。 其次,这个包需要添加到ApplicationConfig类的构造函数中。

package rest;

@ApplicationPath("/")
public class ApplicationConfig extends ResourceConfig 
    public ApplicationConfig()
        register(MultiPartFeature.class);
        packages("rest");
    

【讨论】:

以上是关于为啥在启动 REST 服务时添加注解 FormDataParam 会引发异常?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Spring Rest 服务在第一次请求时很慢?

Annotation 注解开发介绍优势 与好处java为啥采用注解开发

SpringCloud之Feign:REST客户端

我配置了redis注解缓存,为啥不起作用

Salesforce REST 接口集成服务

为啥 AngularJS 应用程序不能在不同的服务器上使用 REST 服务?