一、简介

拦截器体系是struts2重要的组成部分。正是大量的内建拦截器完成了该框架的大部分操作。

比如params拦截器将请求参数解析出来,设置Action的属性。servletConfig拦截器负责将request和response对象传给Action的等等

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

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

理解DRY规则 DRY:               Don‘t Repeat Yourself 意思是不要书写重复的代码。

对于软件开发的新手来说,开发软件时可能很多地方需要重复性的功能和代码,新手会直接选择复制粘贴即可。

一旦需要更改维护这段代码,就要修改很多地方,后期的维护简直是噩梦。 所以有经验的开发人员会将重复代码定义成一个方法,哪里需要哪里调用即可,更改的时候只用修改方法即可。

二、拦截器的意义

上面的例子中当有一天代码中需要调用另一个方法,或者是代码中的方法需要经常切换。

这时候我们又得打开源码,修改所有调用方法的地方。造成这个问题的关键在于 以硬编码的方式调用方法。

为了解决这个问题,我们需要一种机制,所有代码中无需硬编码调用某个方法,但实际上又可以调用方法的功能。

struts2的拦截器就是实现了这种需求。拦截器会在目标方法调用之前之后调用一些方法。

三、拦截器的实现原理

拦截器基于AOP(面向切面编程)思想。 AOP编程方式中,有三个重要的概念

-目标对象:被拦截方法的对象

-被插入的处理方法:定义在拦截器中,会在被拦截方法之前、之后自动调用的方法。方法不能独立存在,必须有载体,载体就是拦截器,拦截器就是包含处理方法的实例。

-代理对象:根据目标对象创建的代理对象。代理对象也称为AOP代理,系统动态生成一个对象,该对象将代替目标对象来使用。AOP代理包含了目标对象的所有方法,AOP代理中的方法会在特定位置插入拦截器方法,然后回调目标对象的处理方法,从而实现了执行目标方法之前或者之后调用拦截器方法。

四、struts2中的拦截器

Struts2框架拦截器

Struts 2框架提供了一个良好的开箱即用的拦截器列表,这些拦截器预先配置好并可以使用。 下面列出了几个重要的拦截器:

序号 拦截器和说明
1 alias

允许参数在请求之间使用不同的别名。

2 checkbox

通过为未检查的复选框添加参数值false,以辅助管理复选框。

3 conversionError

将字符串转换为参数类型的错误信息放置到action的错误字段中。

4 createSession

自动创建HTTP会话(如果尚不存在)。

5 debugging

为开发人员提供一些不同的调试屏幕。

6 execAndWait

当action在后台执行时,将用户发送到中间的等待页面。

7 exception

映射从action到结果抛出的异常,允许通过重定向自动处理异常。

8 fileUpload

便于文件上传。

9

i18n

在用户会话期间跟踪选定的区域。

10 logger

通过输出正在执行的action的名称提供简单的日志记录。

11 params

设置action上的请求参数。

12 prepare

这通常用于执行预处理工作,例如设置数据库连接。

13 profile

允许记录action的简单分析信息。

14 scope

在会话或应用程序范围内存储和检索action的状态。

15 ServletConfig

提供可访问各种基于servlet信息的action。

16 timer

以action执行时间的形式提供简单的分析信息。

17 token

检查action的有效性,以防止重复提交表单。

18 validation

提供action的验证支持。

你可以阅读Struts 2文档,了解上述拦截器的完整信息。接下来我们会告诉你如何在Struts应用程序中使用拦截器。

五、拦截器使用

(一)配置拦截器

            在struts.xml中定义拦截器 

            <interceptor name="拦截器名" class="拦截器类" />

            如果配置拦截器时需要传入拦截器参数,则需要使用param元素。

            <interceptor name="拦截器名" class="拦截器类" >
<param name="参数名">参数值</param>
....
</interceptor> 还可以把多个拦截器组成拦截器栈
<interceptor-stack name="拦截器栈名">
<interceptor-ref name="拦截器一"/>
<interceptor-ref name="拦截器二"/>
....
</interceptor-stack>

(二)使用拦截器或拦截器栈  

  通过<intercept-ref name="拦截器名字" />使用拦截器

(三)自定义拦截器

实现自定义拦截器需要实现Interceptor接口
该接口有三个方法
-void init():拦截器实例化之后调用,只会执行一次,用于初始化资源 -void destory():拦截器销毁之前调用 -String intercept(ActionInvocation invoction)throws Exception:该方法是用户需要实现的拦截动作。 该方法的ActionInvocation包含了被拦截的action引用等所有数据,可以调用该参数的invoke方法放行,如果有下一个拦截器转到下一个拦截器,如果没有就转给Action类的方法。 struts2提供了AbstractInterceptor类实现了Interceptor接口,我们只需要继承这个类即可。

(四)举例:

第一步:实现拦截器:

            public class MyInterceptor extends AbstractInterceptor {
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("拦截器执行:动作方法之前");
//放行
String result=invocation.invoke();
System.out.println("拦截器执行:动作方法之后");
return result;
}
}

第二步:创建action类

                    public class Demo extends ActionSupport {
public String execute(){
System.out.println("执行动作类的execute方法");
return SUCCESS;
}
}

第三步:配置struts.xml文件

                    <package name="demo1" extends="struts-default">
//定义拦截器
<interceptors>
<interceptor name="myinterceptor" class="com.cad.struts2.interceptor.MyInterceptor"></interceptor>
</interceptors> <action name="demo1" class="com.cad.struts2.action.Demo">
//action中使用拦截器,如果action使用了拦截器,则默认的拦截器栈就失效
<interceptor-ref name="myinterceptor"></interceptor-ref>
<result>/Demo.jsp</result>
</action>
</package>

第四步:返回成功的jsp页面

                    <body>
demo1.jsp
<%System.out.println("demo1.jsp执行了"); %>
</body>

输出结果:

                        拦截器之前
执行动作类的execute方法
demo1.jsp执行了
拦截器之后

六、拦截器堆栈

你可以想象,为每个action配置的多个拦截器将很快变得极其难以管理。为此,拦截器使用拦截器堆栈进行管理。这里是直接从struts-default.xml文件展示的一个例子:

<interceptor-stack name="basicStack">
<interceptor-ref name="exception"/>
<interceptor-ref name="servlet-config"/>
<interceptor-ref name="prepare"/>
<interceptor-ref name="checkbox"/>
<interceptor-ref name="params"/>
<interceptor-ref name="conversionError"/>
</interceptor-stack>

上面的堆栈称为basicStack,可以如下所述在你的配置中使用,此配置节点放置在<package ... />节点下。<interceptor-ref ... />标签引用的是在当前拦截器堆栈之前配置的拦截器或拦截器堆栈。因此非常重要的是在配置初始拦截器和拦截器堆栈时,确保name在所有拦截器和拦截器堆栈配置中是唯一的。
我们已经学习了如何将拦截器应用到action中,而拦截器堆栈的应用也是类似的。事实上,使用的标签也是一样的:

<action name="hello" class="com.tutorialspoint.struts2.MyAction">
<interceptor-ref name="basicStack"/>
<result>view.jsp</result>
</action

上述的“basicStack”注册将完整注册hello action的所使用的六个拦截器。要注意的是,拦截器按照它们被配置的顺序执行。例如,在上面的例子中,exception将首先执行,第二个将是servlet-config等。

七、拦截指定方法的拦截器

默认情况下,我们为某个action定义了拦截器,则这个拦截器会拦截该Action的所有方法,如果我们只需要拦截指定方法,此时需要使用struts2拦截器的方法过滤特性。

struts2提供了一个和MethodFilterInterceptor类,该类是AbstractInterceptor的子类。 

该类重写了intercept方法,提供了一个doIntercept(ActionInvocation invocation)抽象方法。 

该类重写的intercept方法已经实现了对Action的拦截行为,通过回调doIntercept来完成具体的拦截逻辑。 

我们需要重写doIntercept方法来实现拦截逻辑。 

实现方法过滤的拦截器和普通的拦截器并没有太大区别,但是这个类中增加了两个方法。
-public void setExcludeMethods(String excludeMethods):指定的方法都不会被拦截
-public void setIncludeMethods(String includeMethods):指定的方法会被拦截 如果一个方法同时被这两个方法指定,则这个方法会被拦截。

 第一步:我们编写一个自定义拦截器:

                public class DemoIntercept extends MethodFilterInterceptor {

                    protected String doIntercept(ActionInvocation invocation) throws Exception {

                        System.out.println("拦截器执行:动作方法之前");
String result=invocation.invoke();
System.out.println("拦截器执行:动作方法之后");
return result;
} }

第二步:在struts.xml中配置:

                    <action name="demo1" class="com.cad.struts2.action.Demo">
<interceptor-ref name="myinterceptor">
//设置不会被拦截的方法
<param name="excludeMethods">execute</param>
//设置被拦截的方法
<param name="includeMethods">login,regist</param>
</interceptor-ref>
<result>/Demo.jsp</result>
</action>

  

  

 

八、拦截器小常识

(1)拦截器和struts2插件的关系

我们需要为struts2扩展新功能时,这时需要开发自己的拦截器,通常我们不可能去修改struts-default.xml文件

而通用功能的拦截器也不应该在某个指定的action中配置。这就需要在struts2插件的struts-plugin.xml文件中配置拦截器。

(2)配置默认拦截器

<default-interceptor-ref name="拦截器或者拦截器栈名"></default-interceptor-ref>

对于多个action都要使用的拦截器,避免了在多个action中重复指定拦截器。

(3)使用拦截器时配置参数

    <interceptor-ref name="myinterceptor">
<param name="参数名"></param>
</interceptor-ref> 用拦截器时配置的参数如果和定义拦截器时配置的参数相同,那么会覆盖定义时的参数。

(4)覆盖拦截器栈里特定拦截器的参数

    有时候,action需要使用拦截器栈,当使用这个拦截器栈,又需要覆盖指定拦截器的参数。
可以通过param来指定,name为 拦截器名字.参数名 <interceptor-ref name="mystack">
<param name="myintercept.name">参数值</param>
</interceptor-ref>

(5)拦截器执行顺序  

invoke方法之前的动作谁排在前面谁执行。

invoke方法之后的动作谁排在后面先执行。

其实这是递归实现。 第一个拦截器执行完,调用invoke方法,如果有下一个拦截器,执行第二个拦截器,然后没有拦截器的话,就执行Action类中的方法,然后返回到第二个拦截器,第二个拦截器执行完毕,然后返回到第一个拦截器。  

例子:实现登录权限控制

当我们访问main.jsp时,触发拦截器,如果没有登录,返回到登陆页面

第一步:先创建一个自定义拦截器:

       public class LoginInterceptor extends MethodFilterInterceptor {

            protected String doIntercept(ActionInvocation invocation) throws Exception {
//获取session,判断session中是否有用户
HttpSession session=ServletActionContext.getRequest().getSession(); //没用户返回到input页面
Object obj=session.getAttribute("user");
if(obj==null){
return "input";
}
//有的话放行
String result=invocation.invoke();
return result;
} }

第二步:创建一个action类

            public class DemoAction extends ActionSupport { 

                //登陆方法,向session中设置
public String login(){
HttpSession session=ServletActionContext.getRequest().getSession();
session.setAttribute("user", "user");
return SUCCESS;
}
public String execute() throws Exception { return SUCCESS;
}
}

第三步:配置我们的struts.xml文件

                <package name="demo8" extends="struts-default">
<!--定义拦截器-->
<interceptors>
<interceptor name="logininterceptor" class="com.cad.struts2.interceptor.LoginInterceptor"></interceptor>
</interceptors> <action name="login" class="com.cad.struts2.action.DemoAction" method="login">
<!--登陆成功,直接跳转到main页面-->
<result type="redirectAction">main</result>
</action> <!--执行main动作时,需要拦截器拦截-->
<action name="main" class="com.cad.struts2.action.DemoAction">
<result>/main.jsp</result>
<result name="input">/login.jsp</result>
<!--使用默认拦截器和我们的拦截器-->
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="logininterceptor"></interceptor-ref>
</action>
</package>

  

  

  

  

  

  

  

  

  

  

(六)Struts2的拦截器的更多相关文章

  1. struts2总结六: Struts2的拦截器

    一.Struts2的系统结构图

  2. 简单理解Struts2中拦截器与过滤器的区别及执行顺序

    简单理解Struts2中拦截器与过滤器的区别及执行顺序 当接收到一个httprequest , a) 当外部的httpservletrequest到来时 b) 初始到了servlet容器 传递给一个标 ...

  3. Struts2使用拦截器完成权限控制示例

    http://aumy2008.iteye.com/blog/146952 Struts2使用拦截器完成权限控制示例 示例需求:    要求用户登录,且必须为指定用户名才可以查看系统中某个视图资源:否 ...

  4. Struts2自定义拦截器Interceptor以及拦截器登录实例

    1.在Struts2自定义拦截器有三种方式: -->实现Interceptor接口 public class QLInterceptorAction implements Interceptor ...

  5. struts2之拦截器

    1. 为什么需要拦截器 早期MVC框架将一些通用操作写死在核心控制器中,致使框架灵活性不足.可扩展性降低, Struts 2将核心功能放到多个拦截器中实现,拦截器可自由选择和组合,增强了灵活性,有利于 ...

  6. Struts2【拦截器】就是这么简单

    什么是拦截器 拦截器Interceptor.....拦截器是Struts的概念,它与过滤器是类似的...可以近似于看作是过滤器 为什么我们要使用拦截器 前面在介绍Struts的时候已经讲解过了,Str ...

  7. 【struts2】拦截器基础

    1)拦截器是什么? 拦截器(Interceptor)是Struts2最强大的特性之一,它是一种可以让你在Action执行之前和Result执行之后进行一些功能处理的机制.来回顾一下官方给出的Strut ...

  8. JavaWeb框架_Struts2_(三)---->Struts2的拦截器

    2. Struts2的拦截器(使用拦截器实现权限控制) 2.1 拦截器的概述 拦截器是Struts2的核心组成部分,它可以动态的拦截Action调用的对象,类似与Servlet中的过滤器.Struts ...

  9. (转)Struts2的拦截器

    http://blog.csdn.net/yerenyuan_pku/article/details/68648101 Struts2的拦截器 拦截器的概述 拦截器,在AOP(Aspect-Orien ...

随机推荐

  1. Java NIO wakeup实现原理

    本文转载自Java NIO wakeup实现原理 导语 最近在阅读netty源码时,很好奇Java NIO中Selector的wakeup()方法是如何唤醒selector的,于是决定深扒一下wake ...

  2. 将AOSP源码导入到Android Studio进行查看

    生成iml和ipr文件 source build/envsetup.sh lunch aosp_x86-eng # 或者直接输入lunch,然后选择对应的target make idegen deve ...

  3. Django自学计划之集装箱货物运输物流仓储一站式ERP系统

    业余开始学习时间:2018年1月 业余学习时间段:每天下班晚饭后时间+无事的星期六和星期天+上班时的空闲时间 自学目标: 1.我们要用管理的思维来写我们的系统! 2.我们要用我们的ERP系统帮助中小集 ...

  4. 微信小程序:如何实现两个按钮在最右侧并排

    要实现的效果: wxml端代码: <view  class="prepare_param">                         <view clas ...

  5. docker轻量级监控-sysdig

    sysdig Sysdig = system(系统)+dig(挖掘).Sysdig 是一个开源系统发掘工具,用于系统级别的勘察和排障,可以把它看作一系列Linux系统工具的组合,主要包括: strac ...

  6. Java基本概念:面向对象

    一.简介 面向过程的思维模式是简单的线性思维,思考问题首先陷入第一步做什么.第二步做什么的细节中. 面向对象的思维模式说白了就是分类思维模式.思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独 ...

  7. deepin 340 USB转console线驱动安装及使用

    刚换DEEPIN系统, 有个路由器要做调整,的确是没windows友好,查了网上资料,归总一下. zhaodong@zhaodong-PC:sudo find / -name serial 进入 zh ...

  8. mac 下如何轻松安装神器 Anaconda

    本文推荐使用homebrew 安装 1.打开终端执行 brew cask install anaconda3 然后就可以喝一杯咖啡了,终端会自动执行安装好 如果终端卡在update homebrew ...

  9. C++类的友元机制说明

    下面给出C++类的友元机制说明(对类private.protected成员访问),需要注意的是,友元机制尽量不用或者少用,虽然它会提供某种程度的效率,但会带来数据安全性的问题. 类的友元 友元是C++ ...

  10. CCF(压缩编码):动态规划+平行四边形优化

    压缩编码 201612-4 一开始看这题还以为是哈夫曼编码的题目,结果是哈夫曼题目的变形. 哈夫曼编码是每次合并任意两堆石子,而这里的题目是合并相邻的两堆石子,而且这里的合并花费是合并两堆石子加上所有 ...