(六)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 ...
随机推荐
- Java NIO wakeup实现原理
本文转载自Java NIO wakeup实现原理 导语 最近在阅读netty源码时,很好奇Java NIO中Selector的wakeup()方法是如何唤醒selector的,于是决定深扒一下wake ...
- 将AOSP源码导入到Android Studio进行查看
生成iml和ipr文件 source build/envsetup.sh lunch aosp_x86-eng # 或者直接输入lunch,然后选择对应的target make idegen deve ...
- Django自学计划之集装箱货物运输物流仓储一站式ERP系统
业余开始学习时间:2018年1月 业余学习时间段:每天下班晚饭后时间+无事的星期六和星期天+上班时的空闲时间 自学目标: 1.我们要用管理的思维来写我们的系统! 2.我们要用我们的ERP系统帮助中小集 ...
- 微信小程序:如何实现两个按钮在最右侧并排
要实现的效果: wxml端代码: <view class="prepare_param"> <view clas ...
- docker轻量级监控-sysdig
sysdig Sysdig = system(系统)+dig(挖掘).Sysdig 是一个开源系统发掘工具,用于系统级别的勘察和排障,可以把它看作一系列Linux系统工具的组合,主要包括: strac ...
- Java基本概念:面向对象
一.简介 面向过程的思维模式是简单的线性思维,思考问题首先陷入第一步做什么.第二步做什么的细节中. 面向对象的思维模式说白了就是分类思维模式.思考问题首先会解决问题需要哪些分类,然后对这些分类进行单独 ...
- deepin 340 USB转console线驱动安装及使用
刚换DEEPIN系统, 有个路由器要做调整,的确是没windows友好,查了网上资料,归总一下. zhaodong@zhaodong-PC:sudo find / -name serial 进入 zh ...
- mac 下如何轻松安装神器 Anaconda
本文推荐使用homebrew 安装 1.打开终端执行 brew cask install anaconda3 然后就可以喝一杯咖啡了,终端会自动执行安装好 如果终端卡在update homebrew ...
- C++类的友元机制说明
下面给出C++类的友元机制说明(对类private.protected成员访问),需要注意的是,友元机制尽量不用或者少用,虽然它会提供某种程度的效率,但会带来数据安全性的问题. 类的友元 友元是C++ ...
- CCF(压缩编码):动态规划+平行四边形优化
压缩编码 201612-4 一开始看这题还以为是哈夫曼编码的题目,结果是哈夫曼题目的变形. 哈夫曼编码是每次合并任意两堆石子,而这里的题目是合并相邻的两堆石子,而且这里的合并花费是合并两堆石子加上所有 ...