首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 其他教程 > 其他相关 >

Struts 二 的拦截器(一)

2012-10-26 
Struts 2 的拦截器(一)?一、 理解拦截器拦截器可以动态地拦截发送到指定 Action 的请求,可以在 Action 执行

Struts 2 的拦截器(一)

?

一、 理解拦截器

拦截器可以动态地拦截发送到指定 Action 的请求,可以在 Action 执行的前后插入某些代码。

通过这种方式,就可以把多个 Action 中需要重复指定的代码提取出来,放在拦截器里定义,从而提供更好的代码重用性。

?

1.1 理解 DRY 规则

? 在软件开发中,有一条非常重要的规则: don't repeat yourself,就是所谓 DRY 规则,意思是不要书写重复代码

?? 在软件开发阶段,因为前期设计的不合理,或者缺乏预见性等原因,可能导致系统的多个地方需要使用相同的代码段。但对于许多刚开始从事软件开发的人而言,包含相同的代码段并不会给他们引起任何麻烦,一路复制粘帖。但如果有一天需要改程序中那些‘相同代码’时,有 1000 个地方,就要改 1000 个地方,工作量巨大。

?? 在这种情况下,一般会把‘相同的代码’定义成一个方法,直接调用这个方法,如果需要修改,只需要该一个方法就行了,这样大大降低了软件后期维护的复杂度。

?

1.2 拦截器的意义

?

?上面已经介绍了,把重复代码放在一个方法内(这里称为 方法1),这样程序要修改只要修改这个方法。但是这样也产生了另一个隐藏问题: 如果要弃用方法1,改用方法2,一样有 1000 个地方,就需要改 1000 个地方,造成这种结果是因为以硬编码方式调用了方法1

?

? Struts 2 的拦截器就可实现这种需求: 称某个实例是一个拦截器时,这是就其行为上而言: 从代码角度来看,拦截器就是一个类,这个类也包含方法,只是这个方法是个特殊方法,它会在目标方法调用之前 ”自动“ 执行

?

? 对比直接调用方法与拦截器的关键区别在于 :? 如果不使用拦截器,代码中需要显式通过代码来调用目标方法,如果使用拦截器,则该方法的调用是由系统完成的。

?

? 通过以上对比,发现拦截器的优势: 拦截器提供了更高层次的解耦,目标代码无需手动调用目标方法,而是由系统完成,从而将这种调用从代码层次上升到更高层次,从而提供了更高层次的解耦。

?

提示 : 计算机本身是无法 “自动” 调用拦截器方法,它甚至无法知道到底是应该调用拦截器方法一,还是调用拦截器方法二。对 Struts 2 框架而言,程序通过配置文件来管理拦截器,从而让系统明白: 何时应该调用哪个拦截器。

?

1.3 拦截器的实现原理

?

?下面用 JDK 动态代理为例来介绍如何调用拦截器方法。

? 因为 JDK 动态代理只能对实现了接口的实例来生成代理,因此要提供 Dog 接口

?

Dog

?如果需要在配置拦截器时传入参数,则如下:

?

还可以把多个拦截器连在一起组成拦截器栈

完全可以认为拦截器栈是一个更大的拦截器,如下:

?

因为拦截器栈与拦截器的功能几乎完全相同,因此可能: 拦截器栈里也可包含拦截器栈

?

系统为拦截器指定参数有 2 个时机:

 ● 定义拦截器时定义参数值: 这种参数值将作为拦截器参数的默认参数值

 ● 使用拦截器时指定参数值: 在配置 Action 时候为拦截器参数指定值。

如下 :

?

注意 : 有 2 个时机为拦截器指定参数值,一个是当定义拦截器 (通过 <intercepter .../> 来定义拦截器)时指定拦截器的参数值;另一个是当使用拦截器 (通过 <interceptor-ref .../> 使用拦截器)时指定拦截器的参数值。前者指定的是拦截器参数的默认值。

?

如果在两个时机为同一个参数指定了不同的参数值,则使用拦截器时指定的参数值将会覆盖默认的参数值。

?

2.2? 使用拦截器

?

?一旦定义了拦截器和拦截器栈后,就可以使用这个拦截器或拦截器栈来拦截 Action 了,拦截器、拦截器栈的拦截行为将会在 Action execute() 方法执行之前被执行

?

?通过 <interceptor-ref .../> 元素可以在 Action 内使用拦截器:

 ● conversionError : 这是一个负责处理类型转换错误的拦截器,它负责将类型转换错误从 ActionContext 中取出,并转换成 Action 的 FieldError 错误

 ● createSession : 负责创建一个 HttpSession 对象,主要用于那些需要有 HttpSession 对象才能正常工作的拦截器中。

 ● debugging : 当使用 Struts 2 的开发模式时,这个拦截器会提供更多的调试信息

 ● execAndWait : 后台执行 Action, 负责将等待画面发送给用户

 ● exception : 负责处理异常,将异常映射为结果

 ● fileUpload : 用于文件上传,负责解析表单中文件域的内容

 ● i18n : 支持国际化的拦截器,负责把所选的语言、区域放入用户 Session 中

 ● logger : 负责日志记录的拦截器,主要是输出 Action 名字

 ● modelDriven : 用于模型驱动的拦截器,当某个 Action 类实现了 ModelDriven 接口时,负责把 getModel() 方法的结果放入 ValueStack 中

 ● scopedModelDriven : 如果一个 Action 实现了一个 ScopedModelDriven 接口,该拦截器负责从指定生存范围中找出指定的 Model ,并将通过 setModel 方法将该 Model 传给 Action 实例

 ● params : 负责解析 HTTP 请求中的参数,并将参数值设置成 Action 对应的属性值

 ● prepare : 如果 action 实现了 Preparabel 接口,将会调用该拦截器的 prepare() 方法

 ● staticParams : 负责将 xml 中 <action> 标签下 <param> 标签中的参数值传入 action

 ● scope : 范围转换拦截器,可以将 Action 状态的信息保存到 HttpSession 范围,或者保存到 ServletContext 范围内

 ● servletConfig : 如果某个 Action 需要直接访问 Servlet API ,就是通过这个拦截器实现的

 ● timer : 负责输出 Action 的执行时间,这个拦截器在分析该 Action 的性能瓶颈时比较有用。

 ● token : 用于阻止重复提交,它检查传到 Action 中的 token,从而防止多次提交

 ● tokenSession : 这个拦截器的作用与前一个基本类似,只是它把 token 保存在 HttpSession 中

 ● validation : 通过执行在 xxxAction-validation.xml 中定义的校验器,从而完成数据校验

 ● workflow : 负责调用 Action 类中的 validate 方法,如果校验失败,则返回 input 逻辑视图

 ● store : 负责将 Action 的 messages、errors 、fieldErrors 保存到 session,也负责从 session 中读取 Action 的 messages、errors、fieldErrors

 ● checkbox : 负责检测那些没有勾选的复选项,为它们添加默认值(false)

 ● roles : 是一个 JAAS ( Java Authentication and Authorization Service, Java 授权和认证服务 ) 拦截器,只有当浏览者取得合适的授权后,才可以调用该拦截器拦截的 Action

 ● annotationWorkflow : 这是支持 Struts 2 “零配件” 特性的拦截器

?

大部分时候,开发者无需手动控制这些拦截器,因为 struts-default.xml 文件中已经配置了这些拦截器,只要我们定义的包继承了系统的 struts-default 包,就可以直接使用这些拦截器

?

3.2? struts-default.xml 里配置的拦截器

?

struts-default.xml 文件是 Struts 2 默认的配置文件,不管什么时候,肯定会加载

一般情况下,直接使用系统的 defaultStack 拦截器栈即可,虽然它可能会做一些额外的拦截工作,但对系统不会有太大的影响。如果开发者对每个拦截器所做的工作非常熟悉,而且可以灵活地组合必须的拦截器,对 Struts 2 性能优化是有帮助的,但是一般推荐直接使用 defaultStack

?

因为 Struts 2 的? struts-default 包中指定 defaultStack 拦截器栈是默认的拦截器,因此如果用户定义的包继承了 struts-default 包,则也会将 defaultStack 拦截器栈作为默认的拦截器栈。这意味着: 如果系统中的 Action 配置没有指定拦截器引用,系统会将 defaultStack 拦截器栈自动作用于该 Action

?

?

?

?

?

热点排行