过滤顺序和 web.xml 内容
Posted
技术标签:
【中文标题】过滤顺序和 web.xml 内容【英文标题】:Filter order and web.xml content 【发布时间】:2017-09-10 18:28:12 【问题描述】:好吧,直截了当: 我用 Eclipse 创建了两个过滤器(Filter1 和 Filter2)和一个 servlet(DisplayHeader)来查看过滤器的执行顺序。 我使用 Tomcat 8.5 作为目标运行时。
新建/动态网络项目/ 带有上下文根 / 并检查了“生成 web.xml delpoyment 描述符”
Filter1 在执行时打印“I'm Filter 1”,我将其“链接”到特定的 servlet“DisplayHeader”。 Filter2 它是 2 而不是 1 的孪生兄弟。 DisplayHeader servlet 映射到 /DisplayHeader。
为清楚起见,下面是 Filter1 代码
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
@WebFilter(
urlPatterns = "/Filter1",
servletNames = "DisplayHeader"
)
public class Filter1 implements Filter
/**
* Default constructor.
*/
public Filter1()
// TODO Auto-generated constructor stub
/**
* @see Filter#destroy()
*/
public void destroy()
// TODO Auto-generated method stub
/**
* @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
*/
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
// TODO Auto-generated method stub
// place your code here
System.out.println("I'm Filter 1");
// pass the request along the filter chain
chain.doFilter(request, response);
/**
* @see Filter#init(FilterConfig)
*/
public void init(FilterConfig fConfig) throws ServletException
// TODO Auto-generated method stub
好吧,当我在 Tomcat (Tomcat v8.5) 上运行 servlet 时,它会打印出来
I'm Filter 1
I'm Filter 2
表示Filter1在Filter2之前执行。
我读到过滤器的执行顺序来自 web.xml 文件中的映射顺序, 所以我希望在 web.xml 文件中的某个地方找到类似
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/DisplayHeader</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/DisplayHeader</url-pattern>
</filter-mapping>
我应该按顺序倒过来……
问题是:当我打开我的项目的 web.xml(从项目资源管理器,见下图)文件时,我只看到这个:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>SetFilterOrder</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
web.xml location in the explorer
我只是缺少正确的 web.xml 文件路径还是这个 web.xml 是使用“生成 web.xml delpoyment 描述符”选项的结果?
【问题讨论】:
【参考方案1】:根据我的经验,过滤器链从根开始向上工作。
假设你有:
domain.com/loggedInArea/UserProfile/Address.jsp.
如果您对每个级别都有过滤器,它们将从“最短” URL 开始执行到“最长”:
@WebFilter("/*")
@WebFilter("/loggedInArea/*")
@WebFilter("/loggedInArea/UserProfile/*")
@WebFilter("/loggedInArea/UserProfile/Address.jsp")
您不能真正使用 URL 过滤器通配符,因为您可以在例如搜索文件名时使用它们。所以,你可以搜索
Addr*.jsp
但您不能使用它来指定 WebFilter URL
如果我理解正确,您提到的示例只是您为练习 WebFilters 而创建的东西 - 绝对没问题 - 而不是您正在从事的项目的要求。我想不出一个现实生活中的例子,您需要确定过滤器的执行顺序而不是 URL 级别。
你不能拥有
@WebFilter("/loggedInArea/UserProfile/Address.*p")
@WebFilter("/loggedInArea/UserProfile/Addr*sp")
因为您必须使用特定的文件名,而且它们是互斥的。
如果您有两个具有相同 URL 的不同过滤器
@WebFilter("/loggedInArea/UserProfile/*")
@WebFilter("/loggedInArea/UserProfile/*")
(如果你有这个,Tomcat 甚至可能会拒绝启动,不确定)那么这一切当然应该被浓缩成一个过滤器,你可以在其中控制流量。
【讨论】:
【参考方案2】:从我所做的阅读来看,Servlet 3.0 似乎没有提供一种通过注释定义顺序的方法。因此,要定义顺序,您必须使用 web.xml。它可能使用的顺序可能是字母顺序,也可能只是运气不好,当它进行注释扫描时,哪些类首先出现。您可以测试一下是否弄乱了过滤器名称或过滤器类名称。最终你不能依赖这个。可以肯定的是,您似乎必须恢复到 web.xml。
参考:How to define servlet filter order of execution using annotations in WAR
http://www.concretepage.com/java-ee/jsp-servlet/how-to-use-filter-in-servlet-3-with-webfilter-annotation
http://javabycode.com/java-frameworks/servlet-jsp/filter-servlet-3-using-webfilter-annotation-example.html
【讨论】:
谢谢。如果您使用注释是不可能的,这似乎仍然很奇怪。好吧,就这样吧。 我同意这似乎确实存在他们应该修复的差距。您是否考虑过使用 Spring MVC 代替 JEE?在 Spring 中,您绝对可以在代码中执行此操作,而无需 web.xml。 我是这方面的真正新手。我只是在网上查看 servlets 教程,过滤器主题也弹出了。如果我需要更深入地研究这个问题,我会记住你的建议:) @JoseMartinez 关于订单的注意事项 - 根据我的经验,过滤器链从根开始向上工作。假设您有:domain.com/loggedInArea/UserProfile/Address.jsp。如果每个级别都有一个过滤器,它们将按以下顺序执行:首先是带有 url 模式“/*”的过滤器,然后是 /"/loggedInArea/*",然后是 "/loggedInArea/UserProfile/*",然后是 "/登录区域/用户配置文件/Address.jsp”。当您说您无法控制订单时,我完全同意,但这并不是完全随机的。另外 - 我不会向我最大的敌人推荐 Spring,但我猜这是偏好 :) @Dan 很好。感谢您添加它。我认为这值得在这里自己回答。以上是关于过滤顺序和 web.xml 内容的主要内容,如果未能解决你的问题,请参考以下文章
除了在 web.xml 中声明过滤器之外,还有啥方法可以指定过滤器的顺序吗?