在过滤器链

时间:2018-05-19 17:57:31

标签: java spring spring-boot

我使用Jersey和Spring Boot,需要配置Jersey作为Servlet过滤器运行。这样做的问题是,使用Multipart,我们会收到所有请求的400 Bad Request。进一步的研究表明,HiddenHttpMethodFilter是问题所在,因为它读取了请求参数,导致请求流被读取,没有留下泽西的任何内容。

要解决此问题,我正在执行HiddenHttpMethodFilter的Javadoc中所述的内容:将Jersey过滤器配置为在此过滤器之前运行。

  

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

要配置Jersey过滤器的顺序,请使用Spring Boot属性

spring.jersey.filter.order=-100000

这很有效。以下是过滤器链订单的前后日志

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

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

因此,您可以看到jerseyFilter已正确重新排序。但requestContextFilter需要在jerseyFilter之前执行。我正在寻找JerseyAutoConfiguration的来源,它显示requestContextFilter顺序设置为泽西过滤器配置的-1。但这似乎并不是正在发生的事情

@Bean
@ConditionalOnMissingBean
public FilterRegistrationBean<RequestContextFilter> requestContextFilter() {
    FilterRegistrationBean<RequestContextFilter> registration = new FilterRegistrationBean<>();
    registration.setFilter(new RequestContextFilter());
    registration.setOrder(this.jersey.getFilter().getOrder() - 1);
    registration.setName("requestContextFilter");
    return registration;
}

在进一步调查中,我发现上面列出的所有过滤器都有一个Ordered子类,我假设它是注册的。例如,有一个OrderedRequestContextFilter,订单设置为-105。如果我设置了DEBUG日志记录,我可以看到情况仍然如此,即使我设置了泽西过滤器顺序属性

'characterEncodingFilter'; order=-2147483648,
'hiddenHttpMethodFilter'; order=-10000,
'httpPutFormContentFilter'; order=-9900,
'requestContextFilter'; order=-105,

基本上,我只想弄清楚更改RequestContextFilter的过滤器顺序的正确方法是什么,以便它在Jersey过滤器之前执行。

1 个答案:

答案 0 :(得分:1)

所以在WebMvcAutoConfiguration,我找到了

@Bean
@ConditionalOnMissingBean({ RequestContextListener.class,
        RequestContextFilter.class })
public static RequestContextFilter requestContextFilter() {
    return new OrderedRequestContextFilter();
}

所以我尝试添加相同的bean并在OrderedRequestContextFilter上设置顺序。

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

这很有效,我得到了我想要的结果;在泽西过滤器之前订购了RequestContextFilter

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