Struts 2中的过滤器和拦截器对比

23

拦截器和过滤器之间到底有什么区别?我知道拦截器在操作前后递归地触发,而过滤器可以配置在操作和特定url模式上触发。但是如何知道何时使用每个组件呢?

在我阅读的Struts 2书籍中,似乎正在推动使用拦截器,并且我甚至按照教程编写了一个认证拦截器以确保用户已登录。但是,如果用户尝试访问没有与其关联的操作的URL,则拦截器无法捕获它,这意味着我必须将每个我想要保护的jsp关联到一个操作上。这看起来不正确。

我可以创建一个处理URL的身份验证过滤器,以便不必这样做,但是,这样做的话,拦截器还有什么意义呢?


10
将您的 .jsp 文件放在 /WEB-INF 文件夹中是一个好习惯。这样它们就无法通过 URL 直接请求。相反,用户应该通过操作访问它们,然后转发到正确的 jsp(根据结果而定)。 - Pat
6个回答

45
最重要的区别是“拦截器”是Struts 2框架的一部分,只是由Struts 2框架处理请求的一部分。另一方面,“过滤器”是Servlet规范的一部分;换句话说,它们是Servlet API的一部分。如果您正在使用Struts 2,则应该使用拦截器来包装功能以围绕您的Struts 2操作执行。如果您想在未被Struts 2处理的Web应用程序请求周围包装功能,则过滤器可能更合适。
顺便提一下,整个Struts 2框架都部署在筛选器中,该筛选器在您的Web应用程序中进行配置,在Web应用程序的部署描述符(web.xml)中声明:
    <filter>
        <filter-name>struts2</filter-name>
        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
    </filter>

     <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

这个过滤器配置了捕获所有请求URL模式,是整个Struts 2框架的入口点。

希望对你有所帮助。


感谢您提供有关Servlet规范和Struts 2框架区别的提示。 - asgs
它们具有相同的功能。 - hiway
2
@hiway 我不会说它们具有相同的功能,我会说它们在两个非常不同的上下文中担任相同的功能角色。 - chad

5
拦截器栈在每个请求上都会触发。
过滤器仅适用于定义它们的URL。
编辑--您可以根据需要使用其中之一。假设您需要验证每个请求是否存在Cookie,请使用拦截器。假设您需要在某些请求上弹出外部应用程序(由URL驱动),请使用过滤器。
我认为拦截器是更常用的工具...
为什么会有一个没有相关操作的URL?

1
拦截器栈仅对在该栈为默认栈的包中定义的请求触发,也就是说,我可以在其他包中定义操作,而拦截器不会触发,就像过滤器一样,它可以有选择性地应用于所有URL。要验证cookie是否存在,我不明白为什么您不使用过滤器。如果您有一个简单的JSP,例如图像上传表单,可能没有任何需要操作的工作。我应该为每个JSP创建操作类吗?即使它们是空的? - JPC
没错,如果一个操作没有意义,那就不要加上它。尽管我记得一个操作可以通过返回一个字符串值来路由到jsp。我认为你会发现有很多做事情的方法,所以有一些重叠是很自然的。 - hvgotcodes
我想我只是在寻找最佳实践,但一直没有找到答案。特别是现在有了Convention插件,如果我有一个上传表单,我可以通过输入“/upload-form”来像操作一样访问它,甚至不必直接访问jsp。问题是,这不会触发拦截器,所以过滤器是唯一能捕获它的东西。 - JPC

4
什么是拦截器?
Struts 2框架使用拦截器的概念,通过不同的操作共享一些常见问题的解决方案。
我们知道,框架在请求提交时会调用特定的Action对象。但在执行Action之前,该调用会被某个其他对象拦截,以提供所需的附加处理。
同样,在执行Action后,该调用可以再次被拦截。这个拦截对象称为拦截器。
因此,使用拦截器的目的是允许更好地控制控制器层,并分离适用于多个操作的某些常见逻辑。
Struts 2框架已经提供了自己的一组拦截器,可以在应用程序中使用,以在Action类执行之前和之后提供所需的处理。
其中之一是“别名拦截器”,我将在这里进行讨论。
别名拦截器:
别名拦截器用于操作链接。操作链接意味着一个操作在第一个操作成功执行后调用另一个操作。
此拦截器将命名参数别名到不同的参数名称。在操作链接中,当两个不同的操作类共享具有不同名称的公共参数时,使用此拦截器将别名名称给第一个操作类的参数,该参数与第二个操作类的参数名称匹配。
操作的别名表达式应为:
             #{ 'name1' : 'alias1' , 'name2' : 'alias2' }

3
根据Struts 2的生命周期/架构,过滤器之前不会执行任何拦截器。所以如果您的请求没有相应的动作映射,则在通过过滤器时会失败。

1
作为经验法则,
过滤器在每个请求之前运行。 Struts 本身就是一个过滤器。
拦截器可以在 Struts 操作之前或之后运行。如果请求不以 .action 结尾,则它们不会运行。
因此,一些过滤器的示例可能包括:
如果要压缩 js 和 css 文件,则应使用过滤器而不是拦截器。
如果您只希望某些 IP 地址访问您的网站,则必须将其开发为过滤器并检查请求 IP 地址。
如果要保护您的网站免受 CSRF 攻击,则必须编写一个过滤器来检查请求中的 CSRF 令牌。
如果要记录您的网站响应时间,请使用过滤器在 chain.doFilter(request, response) 之前和之后计算时间。
理论上,您可以开发一个 Struts Web 应用程序,而无需开发自己的拦截器,只使用过滤器。但是,您将面临许多问题和代码锅炉过滤器。
许多struts 2功能都是使用拦截器构建的,您可以在struts-default.xml(https://struts.apache.org/docs/struts-defaultxml.html)中找到它,该列表将帮助您找到何时可以使用拦截器。 (例如, ParametersInterceptor操作之前运行以将提交的表单值应用于操作)。
在使用拦截器时,您可以轻松访问struts功能,例如从消息资源获取getText、获取当前操作名称和命名空间、更改操作流程。
考虑上述情况,以下是可以通过拦截器开发的一些案例:
  • 如果您希望只有已登录的用户才能访问某些操作,则必须使用拦截器进行开发。
  • 如果您想跟踪用户正在导航的操作。您可以使用拦截器来跟踪访问的操作。
  • 如果您想在单个点处理操作错误,则可以使用拦截器捕获所有invocation.invoke()
拦截器为struts操作提供了过滤器和责任链设计模式,而过滤器则为整个Web应用程序提供此模式。

0

Struts 2框架不依赖于Servlet API。 Struts 2操作与容器无关。通常,servlet上下文表示为简单的映射,允许在隔离中测试操作。

过滤器是Servlet API的一部分,因此Struts 2框架使用拦截器的概念来通过不同的操作共享某些常见问题的解决方案。

此外,您可以轻松编写拦截器和操作类的测试用例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接