如果我们在 WAR 自己的 web.xml中定义特定于 webapp 的 servlet 过滤器,那么过滤器的执行顺序将与在 web.xml中定义它们的顺序相同。
web.xml
但是,如果我们使用 @WebFilter注释定义这些过滤器,那么过滤器的执行顺序是什么,如何确定执行顺序?
@WebFilter
Servlet 3.0规范似乎没有提供关于容器应该如何对通过注释声明的过滤器进行排序的提示。但是,很清楚如何通过 web.xml 文件中的声明对过滤器进行排序。
注意安全。使用具有相互依赖性的 web.xml 文件顺序过滤器。尝试使过滤器的所有顺序独立,以尽量减少使用 web.xml 文件的需要。
确实不能使用 @WebFilter注释定义筛选器执行顺序。但是,为了尽量减少 web.xml的使用,只用 filterName对所有过滤器进行注释就足够了,这样就不需要 <filter>定义,只需要按照所需的顺序对 <filter-mapping>定义进行注释。
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 所要求的,尽管它可以是空的:
<url-pattern>
<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 >
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(); } }