这篇文章讲讲 Struts2 的核心所在——拦截器

一、strut2框架中的拦截器(interceptor)

1.什么是拦截器(interceptor)

  拦截器是strut2框架中提供的一种java类。

作用:

1.可以拦截访问action的请求

2.给这个action加入新的丰富功能(上传、参数自动接收、类型自动转换等等)需要配置之后,指明哪一个拦截器去拦截哪一个action或者哪一些action,这样这个拦截器才会去拦截我们的这个action,每一个拦截器就可以给我们的action加入一个新的功能.

2.拦截器(interceptor)如何工作的

  a.有一个拦截器的类(struts2框架自带的或者我们自己定义的一个类)

b.在配置文件中把这个拦截器类配置出来.

c.指明这个拦截器要拦截哪一个或者哪一些action.

d.客户端发送一个请求访问一个被拦截器拦截的action

e.这个请求会先被struts2的filter所拦截,filter会先检查这个请求是不是请求的action,如果是action的话,那么会再检查这个action有没有被定义的拦截器所拦截,有如果那么就把这个请求交给拦截器去处理.

3.如何自定义一个拦截器

  struts2框架已经写好了很多个拦截器(在struts2的核心jar包),同时也把这些拦截器配置在配置文件里面(在struts-default.xml中).

除此以外,我们还能写自己的的拦截器。

要写一个拦截器,首先要实现一个接口:com.opensymphony.xwork2.interceptor.Interceptor

例如:
public class MyInterceptor implements Interceptor{
public void destroy() {

System.out.println("in destory() of MyInterceptor");

}

public void init() {
System.out.println("in init() of MyInterceptor");

}

//拦截到访问action的情况的时候调用这个方法
public String intercept(ActionInvocation ai) throws Exception {

System.out.println("before...");
//ai.invoke()其实就是帮我们去调用action中将要执行的方法,比如execute方法
//ai.invoke()的返回值其实就是action中方法执行完返回的字符串
String s = ai.invoke();
System.out.println("after...");
return s;
}
}

Init()方法:在服务器起动的时候加载一次,并且只加载一次;

Destroy()方法:当拦截器销毁时执行的方法;

Interceptor()方法:其中里边有一个参数invocation

Invocation.invoke()是如果只有一个拦截器执行完这个方法后,会返回给视图,如果有多个拦截器,它顺序的执行完所有的拦截器,才返回给视图.

然后在struts.xml文件中配置出这个拦截器类:
<interceptors>
<interceptor name="myInterceptor" class="com.briup.web.interceptor.MyInterceptor"></interceptor>
</interceptors>
    最后指明这个拦截器在哪一个action中起作用:
<action name="MyTest">
<result>/index.jsp</result>
<interceptor-ref name="myInterceptor"></interceptor-ref>
</action>

4.拦截器栈

  当前一个action需要被多个拦截器拦截的时候,正常情况下,我们需要在这个action中去引用要使用到的多个拦截器,但是我们可以使用一个拦截器栈去包含那几个拦截器,然后在action中直接引用这个拦截器栈就可以了.

1.一个拦截器栈可以包含多个拦截器

2.一个拦截器栈还可以包含其他拦截器栈

3.定义拦截器或者拦截器栈都要在<interceptors>标签中
例如:
      <interceptors>
<interceptor name="myInterceptor" class="com.briup.web.interceptor.MyInterceptor"></interceptor>
<interceptor-stack name="myStack">
<!-- 这是我们自己定义的一个拦截器 -->
<interceptor-ref name="myInterceptor"></interceptor-ref>
<!-- 这是struts-default.xml文件中定义的一个拦截器 -->
<interceptor-ref name="params"></interceptor-ref>
<!-- 这是struts-default.xml文件中定义的一个拦截器栈 -->
<interceptor-ref name="basicStack"></interceptor-ref>
</interceptor-stack>
</interceptors>

5.默认拦截器/拦截器栈

   在一个package中,我们可以把一个拦截器或者拦截器栈声明为一个默认的拦截器/拦截器栈

作用:将来这个package中所有的action都会被这个默认的拦截器/拦截器栈所拦截。

例如:
     myStack是一个拦截器或者拦截器栈
<default-interceptor-ref name="myStack"></default-interceptor-ref>
   注意:
一般情况下,我们所写的任何action都会被一个叫做defaultStack的拦截器栈所拦截,这个拦截器栈中包含了十几个拦截器,这些拦截器给我们的action提供了很多丰富的功能.因为我们写所有的package都是直接或间接的继承了struts-default.xml文件中的一个名字叫struts-default的package,struts-default包中又把名字叫defaultStack的拦截器栈配置成了一个默认的拦截器栈,那么我们的package就把这个配置继承了过来,所有我们的action正常情况下都会被defaultStack所拦截

但是如果我们一旦指明了某一个action被我们所写的一个拦截器/拦截器栈所拦截,那么这个action就不会被defaultStack拦截了.所以我们可以在action中主动的再声明 这个action被defaultStack所拦截,或者把defaultStack加入到我们自定义的拦截器栈里面(拦截器栈可以包含拦截器栈)

6.package之间的继承

我们可以专门再定义一个package,在这个package里面我们只做拦截器/拦截器栈的定义:
<!-- 在这个package中,我们只定义拦截器/拦截器栈 -->
<package name="MyInter" extends="struts-default" namespace="/">

<interceptors>
<interceptor name="myInterceptor" class="com.briup.web.interceptor.MyInterceptor"></interceptor>
<interceptor-stack name="myStack">
<interceptor-ref name="myInterceptor"></interceptor-ref>
<!-- 这是struts-default.xml文件中定义的一个拦截器栈 -->
<interceptor-ref name="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>

<!-- 声明默认拦截器/拦截器栈 -->
<!-- 当前包中所有的action都会被这个myStack所拦截器 -->
<!-- 继承了当前包的其他包里面的所有action也会被这个myStack所拦截器 -->
<default-interceptor-ref name="myStack"></default-interceptor-ref>

</package>
    然后我们可以让其他的package去继承我们这个MyInter包,这样一来,其他包中的action都会被我们这个MyInter包中的默认拦截器栈myStack所拦截了。 
注意:一定要保证action至少是被defaultStack这个拦截器栈所拦截的.

7.注意:在struts.xml中只定义出来一个拦截器,这个拦截器是不会被初始化和销毁的,在action中引用过以后才能让struts2框架帮我们去初始化这个拦截器,但是还是不能销毁,如果还想销毁的话,那么就要在一个拦截器栈中去引用一下这个拦截器才可以.

二、拦截器(interceptor)和过滤器(filter)的比较

 相同点:
1.都是一种java类

2.都能拦截客户端发给服务器端的请求

3.拦截到请求之后都可以做一些相应的处理,最后还可以把这个请求放行.

4.都需要实现各自相应的接口以及在相应的配置文件中配置.

不同点:

1.拦截器(interceptor)是struts2框架中的定义的,过滤器(filter)是web里面的对象,是J2EE标准里面定义的.

2.拦截器(interceptor)只会拦截器访问action的请求,过滤器(filter)能够拦截所有请求.

3.拦截器(interceptor)定义在struts.xml文件中,过滤器(filter)定义在web.xml文件中.

4.拦截器(interceptor)对象的创建、调用、销毁是struts2框架负责的,过滤器(filter)对象的创建、调用、销毁服务器负责的.

我们自己定义的filter能不能拦截Struts2框架中的action

1.可以拦截

2.需要在web.xml文件中把我们自己的filter配置在struts2的filter的上面才可以.

因为web.xml文件中filter配置的先后顺序控制filter起作用的顺序,同时如果struts的filter先拦截到访问action的请求后,不会把这个请求交给下面的filter,而是交给了他它内部的拦截器(interceptor)了,但是如果我们自己filter拦截到请求之后,还是依然会交给下一个filter,也就是交给struts2的filter.

几个简单的拦截器:

alias:实现在不同请求中相似参数别名的转换。

autowiring:这是个自动装配的拦截器,主要用于当Struts2和Spring整合时,Struts2可以使用自动装配的方式来访问Spring容器中的Bean。

chain:构建一个Action链,使当前Action可以访问前一个Action的属性,一般和<result type="chain" .../>一起使用。

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

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

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

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

exception:这个拦截器负责处理异常,它将异常映射为结果。

fileUpload:这个拦截器主要用于文件上传,它负责解析表单中文件域的内容。

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

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

model-driven:这是一个用于模型驱动的拦截器,当某个Action类实现了ModelDriven接口时,它负责把getModel()方法的结果堆入ValueStack中。

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

params:这是最基本的一个拦截器,它负责解析HTTP请求中的参数,并将参数值设置成Action对应的属性值。

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

static-params:这个拦截器负责将xml<action>标签下<param>标签中的参数传入action。

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

servlet-config:如果某个Action需要直接访问Servlet API,就是通过这个拦截器实现的。
注意:尽量避免在Action中直接访问Servlet API,这样会导致Action与Servlet的高耦合。

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

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

token:这个拦截器主要用于阻止重复提交,它检查传到Action中的token,从而防止多次提交。

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

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

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

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

三、Struts2 注解方式(Annotation)(补充)

1.引入 支持Struts2框架注解开发的jar包 struts2-convention-plugin-2.3.4.1
在struts-2.3.24.1-all\struts-2.3.24.1\lib下找

2.struts.xml
<constant name="struts.convention.action.suffix" value="Action"/>

3.Struts2使用注解开发需要遵循一些规范:

1)Action要必须继承ActionSupport父类;

2)Action所在的包名必须以 .action 结尾

3)类名必须以Action结尾

4.package-info.java
@Namespace("/")
@ParentPackage("struts-default")
package com.briup.action.manager;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;


5.action中常用的注解:
Namespace Annotation
1.通过在ActionClass上定义 @Namespace("/custom")
2.通过 package-info.java 定义
@org.apache.struts2.convention.annotation.Namespace("/custom")
package com.example.actions;

Action Annotation
1. @Action(interceptorRefs={
@InterceptorRef("validation"),
@InterceptorRef("defaultStack")
})
2. chain
@Action("foo")
public String foo() {
return "bar";
}

@Action("foo-bar")
public String bar() {
return SUCCESS;
}

Result Annotation
1.全局,整个类可以访问
2.局部,某个方法可以访问
@Results({
@Result(name="failure", location="fail.jsp")
})
public class HelloWorld extends ActionSupport {
@Action(value="/different/url",results={@Result(name="success", location="http://struts.apache.org", type="redirect")} )
public String execute() {
return SUCCESS;
}
}
可以传递参数:
results={ @Result(name="success",
type="httpheader",
params={"status", "500", "errorMessage", "Internal Error"})}

补充:

          1,@ParentPackage:对应xml配置文件中的package的父包,一般需要继承struts-default。

2,@Namespace:对应配置文件中的nameSpace,命名空间。

3,写在方法前边的注解:

@Action,这个注解对应<action>节点

value(),表示action的请求名称,也就是<action>节点中的name属性;

results(),表示action的多个result;这个属性是一个数组属性,因此可以定义多个Result;

interceptorRefs(),表示action的多个拦截器。这个属性也是一个数组属性,因此可以定义多个拦截器;

exceptionMappings(),这是异常属性,它是一个ExceptionMapping的数组属性,表示action的异常,在使用时必须引用相应的拦截器

4,看一下action中最常用的results中单个result注解的配置吧:
@Result,这个注解对应了<result>节点。这个注解只能应用于action类上。这个注解中也有几个属性:

name(),表示action方法的返回值,也就是<result>节点的name属性,默认情况下是【success】;

location(),表示view层文件的位置,可以是相对路径,也可以是绝对路径;

type(),是action的类型,比如redirect,不指定情况下,框架默认的是dispatcher

这些注解基本上就可以完成我们的功能了,通过这样注解开发,可以代替配置xml的编写。

更多相关文章

  1. 9.JAVA-抽象类定义
  2. 这是我在Java套接字编程中做的一种大家都在谈论的自定义协议吗?
  3. 自定义MapReduce输入格式 - 找不到构造函数
  4. 自定义视图无法工作,直到我触摸屏幕
  5. Java 自定义异常 异常抛出
  6. 云星数据---Apache Flink实战系列(精品版)】:Flink流处理API详解
  7. 企业分布式微服务云SpringCloud SpringBoot mybatis (十四)Spring

随机推荐

  1. Android Tutorials
  2. Android 类菜单栏 以及 透明居中排列
  3. Android 如何判断静音模式
  4. android tween动画
  5. android 应用开发code
  6. Android虚线分割Shape
  7. android颜色对应的xml配置值
  8. Android RelativeLayout 相对布局
  9. android tabhost
  10. Android Input Event Dispatching