如何使用 WAR 中的注释定义 servlet 过滤器的执行顺序

如果我们在 WAR 自己的 web.xml中定义特定于 webapp 的 servlet 过滤器,那么过滤器的执行顺序将与在 web.xml中定义它们的顺序相同。

但是,如果我们使用 @WebFilter注释定义这些过滤器,那么过滤器的执行顺序是什么,如何确定执行顺序?

115471 次浏览

Servlet 3.0规范似乎没有提供关于容器应该如何对通过注释声明的过滤器进行排序的提示。但是,很清楚如何通过 web.xml 文件中的声明对过滤器进行排序。

注意安全。使用具有相互依赖性的 web.xml 文件顺序过滤器。尝试使过滤器的所有顺序独立,以尽量减少使用 web.xml 文件的需要。

确实不能使用 @WebFilter注释定义筛选器执行顺序。但是,为了尽量减少 web.xml的使用,只用 filterName对所有过滤器进行注释就足够了,这样就不需要 <filter>定义,只需要按照所需的顺序对 <filter-mapping>定义进行注释。

比如说,

@WebFilter(filterName="filter1")
public class Filter1 implements Filter {}


@WebFilter(filterName="filter2")
public class Filter2 implements Filter {}

web.xml中只有这样:

<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/url1/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern>/url2/*</url-pattern>
</filter-mapping>

如果您希望将 URL 模式保留在 @WebFilter中,那么您可以这样做,

@WebFilter(filterName="filter1", urlPatterns="/url1/*")
public class Filter1 implements Filter {}


@WebFilter(filterName="filter2", urlPatterns="/url2/*")
public class Filter2 implements Filter {}

但是您仍然应该将 <url-pattern>保留在 web.xml中,因为它是 XSD 所要求的,尽管它可以是空的:

<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern />
</filter-mapping>
<filter-mapping>
<filter-name>filter2</filter-name>
<url-pattern />
</filter-mapping>

不管采用什么方法,在 Tomcat 中,这一切都将失败,直到版本7.0.28,因为当出现没有 <filter><filter-mapping>时,它会窒息。参见 使用 Tomcat,@WebFilter 不能在 web.xml 内部使用 < filter-map >

  1. 让 servlet 筛选器实现 spring Orded 接口。
  2. 在配置类中手动声明 servlet 过滤器 bean。
    import org.springframework.core.Ordered;
    

public class MyFilter implements Filter, Ordered {


@Override
public void init(FilterConfig filterConfig) {
// do something
}


@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// do something
}


@Override
public void destroy() {
// do something
}


@Override
public int getOrder() {
return -100;
}
}




import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;


@Configuration
@ComponentScan
public class MyAutoConfiguration {


@Bean
public MyFilter myFilter() {
return new MyFilter();
}
}