struts2拦截器_动力节点Java学院整理
如何使用struts2拦截器,或者自定义拦截器。特别注意,在使用拦截器的时候,在action里面必须最后一定要引用struts2自带的拦截器缺省堆栈defaultstack,如下(这里我是引用了struts2自带的checkbox拦截器):
<interceptor-ref name="checkbox"> <param name="uncheckedvalue">0</param> </interceptor-ref> <interceptor-ref name="defaultstack"/>(必须加,否则出错)
也可以改为对全局action设置自己需要的拦截器,如下:
在struts.xml里面定义全局的配置设置
<package name="struts-shop" extends="struts-default"> <interceptors> <interceptor-stack name="mystack"> <interceptor-ref name="checkbox"> <param name="uncheckedvalue">0</param> </interceptor-ref> <interceptor-ref name="defaultstack"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="mystack"/>(这句是设置所有action自动调用的拦截器堆栈) </package>
struts-action.xml里面配置action如下:
<package name="logonadmin" extends="struts-shop">(这里扩展struts.xml里面定义的配置就可以了) <action name="logon" class="logonaction"> <result>/jsp/smeishop/admin/index.jsp</result> <result name="error">/jsp/smeishop/admin/logon.jsp</result> <result name="input">/jsp/smeishop/admin/logon.jsp</result> </action> <action name="logout" class="logoutaction"> <result>/jsp/smeishop/admin/logon.jsp</result> </action> </package>
你的拦截器可以正常工作了
struts2自带的配置及其拦截器配置
struts2 拦截器 [interceptor]
拦截器的工作原理如上图,每一个action请求都包装在一系列的拦截器的内部。拦截器可以在action执行直线做相似的操作也可以在action执行直后做回收操作。
每一个action既可以将操作转交给下面的拦截器,action也可以直接退出操作返回客户既定的画面。
如何自定义一个拦截器?
自定义一个拦截器需要三步:
1 自定义一个实现interceptor接口(或者继承自abstractinterceptor)的类。
2 在strutx.xml中注册上一步中定义的拦截器。
3 在需要使用的action中引用上述定义的拦截器,为了方便也可将拦截器定义为默认的拦截器,这样在不加特殊声明的情况下所有的action都被这个拦截器拦截。
interceptor接口声明了三个方法:
public interface interceptor extends serializable { void destroy(); void init(); string intercept(actioninvocation invocation) throws exception; }
init方法在拦截器类被创建之后,在对action镜像拦截之前调用,相当于一个post-constructor方法,使用这个方法可以给拦截器类做必要的初始话操作。
destroy方法在拦截器被垃圾回收之前调用,用来回收init方法初始化的资源。
intercept是拦截器的主要拦截方法,如果需要调用后续的action或者拦截器,只需要在该方法中调用invocation.invoke()方法即可,在该方法调用的前后可以插入action调用前后拦截器需要做的方法。如果不需要调用后续的方法,则返回一个string类型的对象即可,例如action.success。
另外abstractinterceptor提供了一个简单的interceptor的实现,这个实现为
public abstract class abstractinterceptor implements interceptor { public void init() { } public void destroy() { } public abstract string intercept(actioninvocation invocation) throws exception; }
在不需要编写init和destroy方法的时候,只需要从abstractinterceptor继承而来,实现intercept方法即可。
我们尝试编写一个session过滤用的拦截器,该拦截器查看用户session中是否存在特定的属性(login属性)如果不存在,中止后续操作定位到login,否则执行原定操作,代码为:
public class checklogininterceptor extends abstractinterceptor { public static final string login_key = "login"; public static final string login_page = "global.login"; public string intercept(actioninvocation actioninvocation) throws exception { system.out.println("begin check login interceptor!"); // 对loginaction不做该项拦截 object action = actioninvocation.getaction(); if (action instanceof loginaction) { system.out.println("exit check login, because this is login action."); return actioninvocation.invoke(); } // 确认session中是否存在login map session = actioninvocation.getinvocationcontext().getsession(); string login = (string) session.get(login_key); if (login != null && login.length() > 0) { // 存在的情况下进行后续操作。 system.out.println("already login!"); return actioninvocation.invoke(); } else { // 否则终止后续操作,返回login system.out.println("no login, forward login page!"); return login_page; } } }
注册拦截器
<interceptors> <interceptor name="login" class="com.jpleasure.teamware.util.checklogininterceptor"/> <interceptor-stack name="teamwarestack"> <interceptor-ref name="login"/> <interceptor-ref name="defaultstack"/> </interceptor-stack> </interceptors>
将上述拦截器设定为默认拦截器:
<default-interceptor-ref name="teamwarestack"/>
这样在后续同一个package内部的所有action执行之前都会被login拦截。
struts2(xwork)提供的拦截器的功能说明:
拦截器
|
名字
|
说明
|
alias interceptor
|
alias
|
在不同请求之间将请求参数在不同名字件转换,请求内容不变
|
chaining interceptor
|
chain
|
让前一个action的属性可以被后一个action访问,现在和chain类型的result(<result type=”chain”>)结合使用。
|
checkbox interceptor
|
checkbox
|
添加了checkbox自动处理代码,将没有选中的checkbox的内容设定为false,而html默认情况下不提交没有选中的checkbox。
|
cookies interceptor
|
cookies
|
使用配置的name,value来是指cookies
|
conversion error interceptor
|
conversionerror
|
将错误从actioncontext中添加到action的属性字段中。
|
create session interceptor
|
createsession
|
自动的创建httpsession,用来为需要使用到httpsession的拦截器服务。
|
debugging interceptor
|
debugging
|
提供不同的调试用的页面来展现内部的数据状况。
|
execute and wait interceptor
|
execandwait
|
在后台执行action,同时将用户带到一个中间的等待页面。
|
exception interceptor
|
exception
|
将异常定位到一个画面
|
file upload interceptor
|
fileupload
|
提供文件上传功能
|
i18n interceptor
|
i18n
|
记录用户选择的locale
|
logger interceptor
|
logger
|
输出action的名字
|
message store interceptor
|
store
|
存储或者访问实现validationaware接口的action类出现的消息,错误,字段错误等。
|
model driven interceptor
|
model-driven
|
如果一个类实现了modeldriven,将getmodel得到的结果放在value stack中。
|
scoped model driven
|
scoped-model-driven
|
如果一个action实现了scopedmodeldriven,则这个拦截器会从相应的scope中取出model调用action的setmodel方法将其放入action内部。
|
parameters interceptor
|
params
|
将请求中的参数设置到action中去。
|
prepare interceptor
|
prepare
|
如果acton实现了preparable,则该拦截器调用action类的prepare方法。
|
scope interceptor
|
scope
|
将action状态存入session和application的简单方法。
|
servlet config interceptor
|
servletconfig
|
提供访问httpservletrequest和httpservletresponse的方法,以map的方式访问。
|
static parameters interceptor
|
staticparams
|
从struts.xml文件中将<action>中的<param>中的内容设置到对应的action中。
|
roles interceptor
|
roles
|
确定用户是否具有jaas指定的role,否则不予执行。
|
timer interceptor
|
timer
|
输出action执行的时间
|
token interceptor
|
token
|
通过token来避免双击
|
token session interceptor
|
tokensession
|
和token interceptor一样,不过双击的时候把请求的数据存储在session中
|
validation interceptor
|
validation
|
使用action-validation.xml文件中定义的内容校验提交的数据。
|
workflow interceptor
|
workflow
|
调用action的validate方法,一旦有错误返回,重新定位到input画面
|
parameter filter interceptor
|
n/a
|
从参数列表中删除不必要的参数
|
profiling interceptor
|
profiling
|
通过参数激活profile
|
注册并引用interceptor
<package name="default" extends="struts-default"> <interceptors> <interceptor name="timer" class=".."/> <interceptor name="logger" class=".."/> </interceptors> <action name="login" class="tutorial.login"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> <result name="input">login.jsp</result> <result name="success" type="redirect-action">/secure/home</result> </action> </package>
可以将多个拦截器合并在一起作为一个堆栈调用,当一个拦截器堆栈被附加到一个action的时候,要想action执行,必须执行拦截器堆栈中的每一个拦截器。
<package name="default" extends="struts-default"> <interceptors> <interceptor name="timer" class=".."/> <interceptor name="logger" class=".."/> <interceptor-stack name="mystack"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> </interceptor-stack> </interceptors> <action name="login" class="tutuorial.login"> <interceptor-ref name="mystack"/> <result name="input">login.jsp</result> <result name="success" type="redirect-action">/secure/home</result> </action> </package>
上述说明的拦截器在默认的struts2应用中,根据惯例配置了若干个拦截器堆栈,详细情参看struts-default.xml
其中有一个拦截器堆栈比较特殊,他会应用在默认的每一个action上。
<interceptor-stack name="defaultstack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletconfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="i18n"/> <interceptor-ref name="chain"/> <interceptor-ref name="debugging"/> <interceptor-ref name="profiling"/> <interceptor-ref name="scopedmodeldriven"/> <interceptor-ref name="modeldriven"/> <interceptor-ref name="fileupload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="staticparams"/> <interceptor-ref name="params"> <param name="excludeparams">dojo"..*</param> </interceptor-ref> <interceptor-ref name="conversionerror"/> <interceptor-ref name="validation"> <param name="excludemethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludemethods">input,back,cancel,browse</param> </interceptor-ref> </interceptor-stack>
每一个拦截器都可以配置参数,有两种方式配置参数,一是针对每一个拦截器定义参数,二是针对一个拦截器堆栈统一定义所有的参数,例如:
<interceptor-ref name="validation"> <param name="excludemethods">myvalidationexcudemethod</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludemethods">myworkflowexcludemethod</param> </interceptor-ref>
或者
<interceptor-ref name="defaultstack"> <param name="validation.excludemethods">myvalidationexcludemethod</param> <param name="workflow.excludemethods">myworkflowexcludemethod</param> </interceptor-ref>
每一个拦截器都有两个默认的参数:
excludemethods - 过滤掉不使用拦截器的方法和
includemethods – 使用拦截器的方法。
需要说明的几点:
1 拦截器执行的顺序按照定义的顺序执行,例如:
<interceptor-stack name="xastack"> <interceptor-ref name="thiswillrunfirstinterceptor"/> <interceptor-ref name="thiswillrunnextinterceptor"/> <interceptor-ref name="followedbythisinterceptor"/> <interceptor-ref name="thiswillrunlastinterceptor"/> </interceptor-stack>
的执行顺序为:
thiswillrunfirstinterceptor thiswillrunnextinterceptor followedbythisinterceptor thiswillrunlastinterceptor myaction1 myaction2 (chain) mypreresultlistener myresult (result) thiswillrunlastinterceptor followedbythisinterceptor thiswillrunnextinterceptor thiswillrunfirstinterceptor
2 使用默认拦截器配置每个action都需要的拦截器堆栈,例如:
<action name="login" class="tutorial.login"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> <interceptor-ref name="default-stack"/> <result name="input">login.jsp</result> <result type="redirect-action">/secure/home</result> </action>
可以按照如下的方式定义:
<interceptors> <interceptor-stack name="mystack"> <interceptor-ref name="timer"/> <interceptor-ref name="logger"/> <interceptor-ref name="default-stack"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="mystack"/> <action name="login" class="tutorial.login"> <result name="input">login.jsp</result> <result type="redirect-action">/secure/home</result> </action>
3 如何访问httpservletrequest,httpservletresponse或者httpsession
有两种方法可以达到效果,使用actioncontext:
map attibutes = actioncontext.getcontext().getsession();
或者实现相应的接口:
httpsession sessionaware
httpservletrequest servletrequestaware
httpservletresponse servletresponseaware
struts2自定义拦截器实例—只允许从登录页面进入系统
【1】struts.xml:
<!-- 定义一个拦截器 --> <interceptors> <interceptor name="authority" class="org.interceptot.logininterceptor"> </interceptor> <!-- 拦截器栈 --> <interceptor-stack name="mydefault"> <interceptor-ref name="defaultstack" /> <interceptor-ref name="authority" /> </interceptor-stack> </interceptors> <!-- 定义全局result --> <global-results> <!-- 当返回login视图名时,转入/login.jsp页面 --> <result name="login">/login.jsp</result> </global-results> <action name="show" class="org.action.showaction"> <result name="success">/main.jsp</result> <!-- 使用此拦截器 --> <interceptor-ref name="mydefault" /> </action> <!--验证登录用户信息 --> <action name="login" class="org.action.loginaction" method="execute"> <result name="error">/login.jsp</result> <result name="input">/login.jsp</result> </action>
【2】自定义拦截器org.interceptot.logininterceptor:
package org.interceptot; import java.util.map; import com.opensymphony.xwork2.action; import com.opensymphony.xwork2.actioncontext; import com.opensymphony.xwork2.actioninvocation; import com.opensymphony.xwork2.interceptor.abstractinterceptor; public class logininterceptor extends abstractinterceptor { @override public string intercept(actioninvocation invocation) throws exception { // 取得请求相关的actioncontext实例 actioncontext ctx = invocation.getinvocationcontext(); map session = ctx.getsession(); string user = (string) session.get("username"); // 如果没有登陆,即用户名不存在,都返回重新登陆 system.out.println("user:"+user); if (user != null) { system.out.println("test"); return invocation.invoke(); } system.out.println("你还没有登录"); ctx.put("tip", "你还没有登录"); return action.login; //返回一个叫login的result结果 } }
【3】进入主页面的action:org.action.showaction
package org.action; import com.opensymphony.xwork2.actionsupport; public class showaction extends actionsupport { public string execute() { return "success"; } }
【4】loginaction:
private boolean isinvalid(string value) { return (value == null || value.length() == 0); } if (isinvalid(user.getusername())) return input; if (isinvalid(user.getpassword())) return input; //登录成功将user放入session中 httpservletrequest request = servletactioncontext.getrequest(); map map=actioncontext.getcontext().getsession(); map.put("username", user.getusername());
【5】如果我们通过show.action访问main.jsp那么就会被自定义拦截器拦住,拦截器检查session中
是否有值,有证明用户已经登录,没有则为没有登录,那么就会被跳转到登陆页面。
总结
以上所述是小编给大家介绍的struts2拦截器,希望对大家有所帮助