Struts 2 中的过滤器与拦截器
Posted
技术标签:
【中文标题】Struts 2 中的过滤器与拦截器【英文标题】:Filters vs Interceptors in Struts 2 【发布时间】:2011-03-16 11:01:42 【问题描述】:过滤器和拦截器之间真的有什么区别?我意识到拦截器在动作之前和之后以递归方式触发,并且过滤器可以配置为在动作和某些 url 模式上触发。但是你怎么知道什么时候使用它们呢?
在我正在阅读的关于 Struts 2 的书中,似乎正在推送拦截器,我什至按照教程编写了一个身份验证拦截器以确保用户已登录。但是,如果用户尝试访问URL 没有与之关联的操作,拦截器不会捕获它,这意味着我必须将操作与我想要安全的每个 jsp 相关联。这似乎不对。
我可以制作一个处理 URL 的身份验证过滤器,这样我就不必这样做了,但是,拦截器的意义何在?
【问题讨论】:
最好将 .jsp 文件放在 /WEB-INF 文件夹中。这样就不能直接通过 URL 请求它们。相反,用户应该通过 Actions,然后将其转发到正确的 jsp(取决于结果)。 【参考方案1】:最显着的区别是“拦截器”是 Struts 2 框架的一部分,并且只是 Struts 2 框架完成的请求处理的一部分。另一方面,“过滤器”是 Servlet 规范的一部分;换句话说,它们是 Servlet API 的一部分。如果您使用的是 Struts 2,您应该使用拦截器来包装您的 Struts 2 操作周围的功能。如果您试图将功能包装到您的 web 应用程序的请求中,但没有被 Struts 2 处理,那么过滤器可能更合适。
顺便说一句,整个 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 Spec 和 Struts 2 框架差异化的提示。 这意味着它们具有相同的功能。 @hiway 我不会说它们具有相同的功能,我会说它们在两种截然不同的环境中发挥相同的功能作用。【参考方案2】:拦截器堆栈在每个请求时触发。 过滤器仅适用于为其定义的 url。
edit -- 您可以根据需要使用其中一种。假设您需要验证每个请求是否存在 cookie。使用拦截器。假设您需要在某些请求(由 url 驱动)上弹出一个外部应用程序,使用过滤器。
我觉得拦截器是比较常用的工具……
为什么会有一个没有相关操作的 url?
【讨论】:
拦截器堆栈仅针对在该堆栈是默认堆栈的包中定义的请求触发,也就是我可以在其他包中定义拦截器不会触发的操作,例如一个过滤器,它可以是选择性的。过滤器也可以应用于所有 url。要验证是否存在 cookie,我不明白为什么您也不会为此使用过滤器。如果您有一个简单的 jsp,例如图像上传表单,则可能不需要我执行任何操作。我应该为每个jsp制作动作类吗?即使它们是空的? 不,你是对的,如果一个动作没有意义,那么不要把一个动作放进去。虽然据我所知,一个动作可以路由到一个jsp,只是返回一个字符串值。我想你会发现做事有很多方法,所以有一些重叠是很自然的。 我想我只是在寻找最佳实践,并没有找到任何答案。特别是现在使用约定插件,如果我有一个上传表单,我可以通过键入“/upload-form”来访问它,我什至不必直接访问 jsp。问题是,这不会触发拦截器,所以过滤器是唯一能捕获它的东西。【参考方案3】:什么是拦截器?
Struts 2 框架使用拦截器的概念来共享不同操作的一些常见问题的解决方案。
正如我们所知,框架会在提交请求时调用特定的 Action 对象。但在执行 Action 之前,调用会被其他一些对象拦截以提供所需的额外处理。
同样在Action执行后,调用可以再次被拦截。这个拦截对象被称为Interceptor。
所以使用 Interceptor 的目的是为了更好地控制控制器层,并分离一些适用于多个操作的通用逻辑。
Struts 2 框架已经提供了自己的一组拦截器,可以在应用程序中使用它们在 Action 类执行之前和之后提供所需的处理。
其中之一是我将在这里讨论的“别名拦截器”。
别名拦截器:
Alias Interceptor 用于 Action 链接。动作链是指一个动作在成功执行第一个动作后调用另一个动作。
此拦截器将命名参数别名为不同的参数名称。在动作链接中,当两个不同的动作类共享一个不同名称的公共参数时,该拦截器用于为第一个动作类的参数赋予别名,该别名与第二个动作类中的参数名称匹配。
action的别名表达式应该是:
# 'name1' : 'alias1' , 'name2' : 'alias2'
【讨论】:
【参考方案4】:根据 struts 2 生命周期/架构,在过滤器之前不执行任何拦截器。因此,如果您的请求没有操作映射,那么它在通过过滤器时会失败。
【讨论】:
【参考方案5】:根据经验
过滤器在每个request
之前运行。 struts
本身就是一个过滤器。
interceptors
可以在 struts 动作之前、之后运行。如果请求不以.action
结尾,它们将不会运行。
因此,过滤器的一些示例可能是:
如果你想压缩你的js
和css
文件,你应该选择过滤器而不是拦截器。
如果您只希望某些 IP 地址访问您的网站,则必须将其开发为过滤器并检查请求 IP 地址。
如果您想保护您的网站免受 CSRF 攻击,您必须编写一个过滤器来检查请求中的 CSRF 令牌。
如果要记录每个请求时间的站点响应,可以使用过滤器计算chain.doFilter(request, response)
之前和之后的时间
理论上,您无需开发自己的interceptors
并仅使用filters
,就可以开发一个struts Web 应用程序。但是您将面临很多问题并编写锅炉过滤器。
很多 struts 2 特性都是用拦截器构建的,你可以在 struts-default.xml (https://struts.apache.org/docs/struts-defaultxml.html) 中找到它,该列表将有助于找到何时可以使用拦截器。 (例如 ParametersInterceptor
运行 在操作之前 将提交的表单值应用于操作)
在使用拦截器时,您可以轻松访问 struts 功能,例如来自消息资源的getText
,获取当前操作名称和命名空间,更改操作流程。
考虑到上面的一些情况,拦截器可以开发:
如果您希望只有登录用户才能访问某些操作,则必须使用拦截器进行开发。 如果您想跟踪用户正在导航的操作。您可以使用拦截器来跟踪访问过的操作。 如果你想单点处理你的动作错误,你可以使用一个拦截器来捕获所有invocation.invoke()
拦截器为 struts 操作提供过滤器和责任链设计模式,而过滤器为您的整个 Web 应用程序提供这种模式。
【讨论】:
【参考方案6】:Struts 2 Framework 不依赖于 Servlet API。 Struts 2 Actions 不与容器耦合。大多数情况下,servlet 上下文表示为简单的 Map,允许单独测试 Action。
过滤器是 Servlet API 的一部分,因此 Struts 2 框架使用拦截器的概念来共享解决方案,以解决不同操作的一些常见问题。
您还可以轻松地为 Interceptor 和 Action 类编写测试用例。
【讨论】:
以上是关于Struts 2 中的过滤器与拦截器的主要内容,如果未能解决你的问题,请参考以下文章
深入分析JavaWeb Item47 -- Struts2拦截器与文件上传下载