Spring Boot + Jersey类型过滤器 - 服务错误请求400消耗MULTIPART_FORM_DATA

时间:2018-05-17 09:13:25

标签: spring-boot file-upload jax-rs jersey-2.0 servlet-filters

我使用Spring boot v1.5.10 + Jersey v2.25.1,将jersey配置为过滤器来访问静态文件夹文件。我收到的HTTP响应400 Bad Request for service MULTIPART_FORM_DATA

道具将泽西岛配置为过滤器。

spring.jersey.type=filter

如果删除上面的属性,即使用Jersey作为Servlet,该服务正在运行,但我无法访问静态文件夹。

这是控制器,

@POST
@Path("/save")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_JSON)
public ResponseBean save(
        @FormDataParam("fileToUpload") InputStream file,
        @FormDataParam("fileToUpload") FormDataContentDisposition fileDisposition,
        @FormDataParam("fromData") FormDataDto data) {
    // stuff
}

修改

GitHub链接https://github.com/sundarabalajijk/boot-jersey

启动应用时,spring.jersey.type=filter

http://localhost:8080/(有效)

http://localhost:8080/hello.html(有效)

http://localhost:8080/save(不工作) - 使用过邮差。

spring.jersey.type=servlet

http://localhost:8080/(有效)

http://localhost:8080/hello.html(不工作)

http://localhost:8080/save(有效)

Postman request

1 个答案:

答案 0 :(得分:6)

经过一些研究和发现相关问题 1 后,Spring HiddenHttpMethodFilter似乎读取了输入流,这使得它对于过滤器链下游的任何其他过滤器都是空的。这就是为什么我们在Jersey过滤器中获得错误请求的原因;因为实体流是空的。以下是Javadoc的说明

  

注意:由于需要检查POST正文参数,因此在多部分POST请求的情况下,此过滤器需要在多部分处理之后运行。

所以我们需要做的是配置在此Spring过滤器 2 之前调用的Jersey过滤器。基于Spring Boot docs,我们可以使用一个属性来轻松配置此过滤器的顺序。

spring.jersey.filter.order

HiddenHttpMethodFilter的Spring Boot repo中执行Github search,我们可以看到使用的子类OrderedHiddenHttpMethodFilter,其中订单设置为-10000。因此,我们希望将Jersey过滤器的顺序设置为小于该值(更高的优先级)。所以我们可以设置以下值

spring.jersey.filter.order=-100000

如果你现在测试它,它现在应该可以工作。

我们需要解决的另一件事是Spring RequestContextFilter的顺序。这最初配置为在Jersey过滤器之前被命令调用。当我们为泽西过滤器设置上面的订单配置时,RequestContextFilter保持原来的位置。所以我们需要改变这一点。我们只需添加一个bean来覆盖原始bean并设置顺序即可。

@Bean
public RequestContextFilter requestContextFilter() {
    OrderedRequestContextFilter filter = new OrderedRequestContextFilter();
    filter.setOrder(-100001);
    return filter;
}

现在,如果我们在启动时检查日志,我们应该看到我们想要的文件管理器订单。

Mapping filter: 'characterEncodingFilter' to: [/*]
Mapping filter: 'requestContextFilter' to: [/*]
Mapping filter: 'jerseyFilter' to urls: [/*]
Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
Mapping filter: 'httpPutFormContentFilter' to: [/*]

除了

在您的情况下需要将Jersey配置为过滤器的原因是静态内容。如果您没有为Jersey应用程序配置根路径,则默认为/*,这将占用所有请求,包括静态内容的请求。因此,当对静态内容发出请求时,Jersey会抛出404错误。我们将Jersey配置为过滤器并告诉它转发它无法找到的请求。

如果我们只是为Jersey配置根路径,那么我们就不需要担心静态内容的这个问题了,我们可以默认将Jersey配置为servlet。

要更改Jersey应用的基本路径,我们可以将@ApplicatuonPath注释添加到ResourceConfig或我们可以使用属性spring.jersey.application-path

@Component
@ApplicationPath("/api")
public class JerseyConfig extends ResourceConfig {
    ...
}

或在application.properties

spring.jersey.application-path=/api

另见

脚注

<子> 1。要查看[12] 的一些问题 <子> 2。请参阅Change order of RequestContextFilter in the filter chain