(六)Struts2的拦截器
一、简介
拦截器体系是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的拦截器的更多相关文章
- struts2总结六: Struts2的拦截器
一.Struts2的系统结构图
- 简单理解Struts2中拦截器与过滤器的区别及执行顺序
简单理解Struts2中拦截器与过滤器的区别及执行顺序 当接收到一个httprequest , a) 当外部的httpservletrequest到来时 b) 初始到了servlet容器 传递给一个标 ...
- Struts2使用拦截器完成权限控制示例
http://aumy2008.iteye.com/blog/146952 Struts2使用拦截器完成权限控制示例 示例需求: 要求用户登录,且必须为指定用户名才可以查看系统中某个视图资源:否 ...
- Struts2自定义拦截器Interceptor以及拦截器登录实例
1.在Struts2自定义拦截器有三种方式: -->实现Interceptor接口 public class QLInterceptorAction implements Interceptor ...
- struts2之拦截器
1. 为什么需要拦截器 早期MVC框架将一些通用操作写死在核心控制器中,致使框架灵活性不足.可扩展性降低, Struts 2将核心功能放到多个拦截器中实现,拦截器可自由选择和组合,增强了灵活性,有利于 ...
- Struts2【拦截器】就是这么简单
什么是拦截器 拦截器Interceptor.....拦截器是Struts的概念,它与过滤器是类似的...可以近似于看作是过滤器 为什么我们要使用拦截器 前面在介绍Struts的时候已经讲解过了,Str ...
- 【struts2】拦截器基础
1)拦截器是什么? 拦截器(Interceptor)是Struts2最强大的特性之一,它是一种可以让你在Action执行之前和Result执行之后进行一些功能处理的机制.来回顾一下官方给出的Strut ...
- JavaWeb框架_Struts2_(三)---->Struts2的拦截器
2. Struts2的拦截器(使用拦截器实现权限控制) 2.1 拦截器的概述 拦截器是Struts2的核心组成部分,它可以动态的拦截Action调用的对象,类似与Servlet中的过滤器.Struts ...
- (转)Struts2的拦截器
http://blog.csdn.net/yerenyuan_pku/article/details/68648101 Struts2的拦截器 拦截器的概述 拦截器,在AOP(Aspect-Orien ...
随机推荐
- PAUL ADAMS ARCHITECT LTD:拜登上台后,美国房地产走势如何?
受全球经济危机影响,美国经济的复苏之路并不平坦,然而住宅房地产市场却是少数的例外,表现得非常亮眼.而随着美国拜登总统上台的临近,美国房产市场还会持续当前的发展吗?对于这个问题,近日,美国知名房地产公司 ...
- 为什么说NGK公链的商用落地是可行的?
互联网.大数据以及云计算的发展给人们的生活.工作带来了诸多便利,也让人们一次又一次感叹科技的进步.而NGK公链的诞生,更是让众人称之为传奇.其商用落地可行性,也让人惊叹.那么,为什么说NGK公链的商用 ...
- JAVA 批量下载服务器文件到本地指定文件夹并重命名
/** * @功能 下载文件到指定文件夹并重命名 * @param url 请求的路径 * @param filePath 文件将要保存的目录 * @param filename 保存到本地的文件名 ...
- 为什么ConcurrentHashMap,HashTable不支持key,value为null?
ConcurrentHashmap.HashMap和Hashtable都是key-value存储结构,但他们有一个不同点是 ConcurrentHashmap.Hashtable不支持key或者val ...
- 零基础学Python:数据容器
1.常用操作 列表常用操作 在 ipython 中定义一个 列表,例如: l= list() 输入 l. 按下 TAB 键, ipython 会提示 字典 能够使用的函数如下: 可以到官方网址查询使用 ...
- C++的指针,引用,指向指针的引用和Java中的引用
#include <iostream> #include<algorithm> using namespace std; class Test { public: Test(i ...
- golang操作mysql2
目录 Go操作MySQL 连接 下载依赖 使用MySQL驱动 初始化连接 SetMaxOpenConns SetMaxIdleConns CRUD 建库建表 查询 单行查询 多行查询 插入数据 更新数 ...
- 简单的webRTC连接测试
webRTC WebRTC (Web Real-Time Communications) 是一项实时通讯技术,它允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-P ...
- 常见 git 需求整理(持续更新中)
首发于 语雀文档 突然感觉自己对 git 还是挺熟悉的,因为团队里新来的七八号应届生来问我 git 问题,基本没有答不上的情况,但为了能更好地对知识进行整理,还是记录一下为好. (希望能)持续更新.. ...
- FreeBSD jail 折腾记(二)
FreeBSD jail 折腾记(二) 创建jail目录 创建4个 分别是模板 骨架 数据 项目 创建模板目录 mkdir -p /jail/j1 # 然后放入基本目录,上篇说过不再写 创建骨架目录 ...