struts2学习笔记9 ——自定义拦截器
在这个类中,需要实现3个方法:destroy(),init(),intercept(),核心方法是intercept(),该方法完成了主要逻辑。
在该方法中有个参数invocation,类型为ActionInvocation接口,这个接口中最重要的是invoke方法。
intercept 方法可以如此实现:
view plaincopy to clipboardprint?
Stringresult=invocation.invoke();
returnresult;
例如,可以这样来实现自定义拦截器
view plaincopy to clipboardprint?
packagecn.tshining.interceptor;
importcom.opensymphony.xwork2.ActionInvocation;
importcom.opensymphony.xwork2.interceptor.Interceptor;
publicclassMyInterceptorimplementsInterceptor{
publicvoiddestroy(){
System.out.println("destory");
}
publicvoidinit(){
System.out.println("init");
}
publicStringintercept(ActionInvocationinvocation)throwsException{
Stringresult=invocation.invoke();
returnresult;
}
}
配置拦截器
定义好拦截器后,需要在struts.xml中配置使用拦截器,配置使用拦截器有2步:
1.声明拦截器。
在 struts.xml中package元素下增加元素
view plaincopy to clipboardprint?
<interceptors>
<interceptorname="myinterceptor"></interceptor>
</interceptors>
2.使用拦截器
首先需要了解的是,struts2已经定义了一个默认的拦截器栈,拦截器栈就是若干个拦截器或拦截器栈组成的一系列拦截器的集合。
在 struts2-core-2.1.8.jar下struts-default.xml中定义了这个默认的拦截器栈。
在 struts中所有的action都使用了默认的拦截器栈,若想使用自定义的拦截器栈,只用在action中配置即可,但是此时必须显式的写出使用默认拦截器栈的配置信息。
view plaincopy to clipboardprint?
<actionname="register2">
<resultname="success">/success.jsp</result>
<resultname="input">/register2.jsp</result>
<interceptor-refname="myinterceptor"></interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</action>
同时可以在控制台上看到输出的"init",这是由于拦截器在服务器启动时会自动加载,完成初始化。拦截器中定义的intercept方法就是在提交请求时执行的。
用户输入的数据会自动赋值到action中,实际上是底层拦截器起的作用。
在 struts-default.xml中可以看到名为params的拦截器,这个拦截器的作用就是将用户输入的数据注入到Action中的字段中。
使用拦截器参数
在定义拦截器,或者在使用拦截器时可以给拦截器传递参数。
首先在 MyInterceptor类中声明一下字段
public int myparam;
修改 intercept方法:
view plaincopy to clipboardprint?
publicStringintercept(ActionInvocationinvocation)throwsException{
Stringresult=invocation.invoke();
System.out.println(myparam);
returnresult;
}
修改struts.xml中拦截器的定义:
view plaincopy to clipboardprint?
<interceptors>
<interceptorname="myinterceptor">
<paramname="myparam">1</param>
</interceptor>
</interceptors>
然后运行该程序,在register2.jsp中输入正确数据提交后就会在控制台中输出1.
也可以在拦截器调用时再传入参数:
view plaincopy to clipboardprint?
<actionname="register2">
<resultname="success">/success.jsp</result>
<resultname="input">/register2.jsp</result>
<interceptor-refname="myinterceptor">
<paramname="myparam">2</param>
</interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</action>
此时重启服务器,在register2.jsp中输入正确的数据之后,可以看到控制台中输出2.
注意此时并没有删除之前拦截器定义时的参数,由此可见,在拦截器调用时的参数比拦截器定义时优先级高。
上面的拦截器调用中使用到了默认拦截器栈,当然自己也可以自定义默认拦截器栈。
view plaincopy to clipboardprint?
<interceptors>
<interceptorname="myinterceptor">
<paramname="myparam">1</param>
</interceptor>
<interceptor-stackname="myDefaultStack">
<interceptor-refname="myinterceptor"></interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-refname="myDefaultStack"></default-interceptor-ref>
这样,这个自定义的默认拦截器栈中包含了自定义的拦截器和struts2定义的默认拦截器栈。
在拦截器栈的定义中,既可以引用拦截器,也可以引用拦截器栈。
在 action中没定义拦截器时,会使用默认拦截器。
当然 struts2提供了一个简便的创建自定义拦截器的方法。
只需要继承AbstractInterceptor类,该类空实现了Interceptor接口的init和destroy方法,因此只用实现 intercept方法即可。
在这里我们override AbstractInterceptor的init方法。
view plaincopy to clipboardprint?
packagecn.tshining.interceptor;
importcom.opensymphony.xwork2.ActionInvocation;
importcom.opensymphony.xwork2.interceptor.AbstractInterceptor;
publicclassMyInterceptor2extendsAbstractInterceptor{
@Override
publicStringintercept(ActionInvocationinvocation)throwsException{
Stringresult=invocation.invoke();
returnresult;
}
@Override
publicvoidinit(){
System.out.println("init2");
}
}
在<interceptor-ref name="myinterceptor"></interceptor-ref>下面增加以下内容:
view plaincopy to clipboardprint?
<interceptor-refname="myinterceptor2"></interceptor-ref>
这样就将myinterceptor2增加到了默认拦截器栈中,查看控制台输出会看到:
init
init2
销毁时会看到:
destory2
destory
这是由于先配置的拦截器先执行,结束时后配置的拦截器先执行
在这里拦截器的执行顺序为:
myintercept——myintercept2——action——myintercept2——myintercept
需要说明的是一定要在action中引用拦截器才会使用拦截器,拦截器拦截的是Action中的execute或自定义的逻辑处理方法。
当然也可以让拦截器拦截指定的方法,那么我们需要继承MethodFilterinterceptor类
view plaincopy to clipboardprint?
packagecn.tshining.interceptor;
importcom.opensymphony.xwork2.ActionInvocation;
importcom.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
publicclassMyInterceptor3extendsMethodFilterInterceptor{
@Override
protectedStringdoIntercept(ActionInvocationinvocation)throwsException{
Stringresult=invocation.invoke();
System.out.println("doing");
returnresult;
}
}
在struts.xml中声明拦截器
view plaincopy to clipboardprint?
<interceptorname="myinterceptor3"></interceptor>
然后在 Action中引用此拦截器。
首先查看MethodFilterinterceptor,它接受两个参数,
excludeMethods:排除的方法,多个方法间用逗号隔开
includeMethods:包含的方法,多个方法间用逗号隔开
在 struts.xml中如下配置
view plaincopy to clipboardprint?
<interceptor-refname="myinterceptor3">
<paramname="excludeMethods">test,execute</param>
<paramname="includeMethods">test</param>
</interceptor-ref>
那么该拦截其将会拦截test方法,因为include比exclude优先级高
在 com.opensymphony.xwork2.interceptor包里面还有一个重要的接口PreResultListener,查看文档。
* PreResultListeners may be registered with an ActionInvocation to get a callback after the Action has been executed but before the Result is executed.
注释:
PreResultListeners 可以注册到ActionInvocation,当Action执行完毕但是在返回结果之前调用。
也就是在action的execute执行结束之后,在渲染页面前调用。
首先实现自己的PreResultListeners类
view plaincopy to clipboardprint?
packagecn.tshining.interceptor;
importcom.opensymphony.xwork2.ActionInvocation;
importcom.opensymphony.xwork2.interceptor.PreResultListener;
publicclassMyListenerimplementsPreResultListener{
publicvoidbeforeResult(ActionInvocationinvocation,StringresultCode){
System.out.println(resultCode);
}
}
修改自己的拦截器MyInterceptor3中的 doIntercept方法。
view plaincopy to clipboardprint?
protectedStringdoIntercept(ActionInvocationinvocation)throwsException{
invocation.addPreResultListener(newMyListener());
Stringresult=invocation.invoke();
System.out.println("doing");
returnresult;
}
注意PreResultListeners必须向 ActionInvocation实例去注册,而且注册要在调用ActionInvocation实例的invoke方法之前。
当在 register2.jsp中输入正确的数据时,在控制台上可以看到输出的success信息。
该执行过程为:
拦截器 ——validate——execute——beforeResult——结束
拦截器的应用
用拦截器进行权限校验
首先分析一下这个示例的工作流程:
首先用户从login2.jsp登陆,只有username输入hello,password输入world,然后跳转到register2.jsp进行注册操作。
如果用户直接访问register2.jsp,提交后将直接跳转回login2.jsp。
1.首先我们修改struts2.xml,让用户在login2.jsp中输入正确页面之后,将页面转到register2.jsp。
view plaincopy to clipboardprint?
<actionname="login">
<resultname="success">/register2.jsp</result>
<resultname="input">/login2.jsp</result>
<resultname="failer">/login2.jsp</result>
</action>
2.修改LoginAction类中execute方法
view plaincopy to clipboardprint?
publicStringexecute()throwsException{
if("hello".equals(this.getUsername())
&&"world".equals(this.getPassword())){
Map<String,Object>map=ActionContext.getContext().getSession();
map.put("user","login");
return"success";
}else{
this.addFieldError("username","usernameorpassworderror");
return"failer";
}
}
在该方法中,若用户输入正确信息后,会获得session对象,并把 user和login存到session中。
struts2 的Action中获得session对象的方法是
Map map = ActionContext.getContext().getSession();
struts 将session从servlet容器中抽离出来了,形成了一个map,更利于单元测试
3.新建一个拦截器。
view plaincopy to clipboardprint?
packagecn.tshining.interceptor;
importjava.util.Map;
importcom.opensymphony.xwork2.Action;
importcom.opensymphony.xwork2.ActionInvocation;
importcom.opensymphony.xwork2.interceptor.AbstractInterceptor;
publicclassAuthInterceptorextendsAbstractInterceptor{
@Override
publicStringintercept(ActionInvocationinvocation)throwsException{
Map<String,Object>map=invocation.getInvocationContext().getSession();
if(map.get("user")==null){
returnAction.LOGIN;
}else{
returninvocation.invoke();
}
}
}
在这个拦截器中,获得session对象的方法是
view plaincopy to clipboardprint?
Map<String,Object>map=invocation.getInvocationContext().getSession();
因此,当session中不存在user的值为login时,拦截器将返回Action.LOGIN,在struts.xml中返回结果为login将跳转到 login2.jsp。
这样便可以实现一个简单的用户校验了。
4.配置action
view plaincopy to clipboardprint?
<actionname="register2">
<resultname="success">/success.jsp</result>
<resultname="input">/register2.jsp</result>
<resultname="login">/login2.jsp</result>
<interceptor-refname="logininterceptor"></interceptor-ref>
<interceptor-refname="defaultStack"></interceptor-ref>
</action>
这样就可以正常工作了。
当然也可以不在Action中定义login的结果跳转,而直接在全局结果中配置。将下面代码放到Action配置前即可正常工作。
view plaincopy to clipboardprint?
<global-results>
<resultname="login">/login2.jsp</result>
</global-results>
这样就定义了一个全局结果页面。
直接进入到register2.jsp,点提交后,会发现地址栏跳到了http://localhost:8888/struts2 /register.action
结果重定向
前面在结果转发时都是用到了请求转发,实际上struts2定义了很多结果类型,我们可以使用重定向试试。
打开 struts2-core-2.1.8.jar,查看里面的struts-default.xml,其中定义了很多结果类型。
其中的 redirect代表的就是重定向。
然后将上面Action配置中作如下修改:
view plaincopy to clipboardprint?
<resultname="login"type="redirect">/login2.jsp</result>
然后重启服务器,直接进入到register2.jsp,点提交后,会发现地址栏跳到了http://localhost:8888/struts2 /login2.jsp
这就是重定向。在struts2中默认是dispatcher。
下次将学习struts2的文件上传与下载。
更多阅读
如何自定义文件夹图标 win7自定义文件夹图标
如何自定义文件夹图标——简介如何制作个性的文件夹图标,一眼就区别开不同的文件夹。如何自定义文件夹图标——工具/原料png图片转化ico图片软件美图秀秀如何自定义文件夹图标——方法/步骤如何自定义文件夹图标 1、从百度图片里
qq空间怎么免费设置背景 qq空间免费自定义背景
qq空间怎么免费设置背景——简介QQ空间采用模块化的设计理念,为我们自定义QQ版面提供了方便的方法,只需要通常简单的拖动即可设计出唯美的个性化风格空间。下面就与小编一起来学习一下QQ空间背景的设计方法。qq空间怎么免费设置背景
怎样自定义QQ空间开场动画? qq空间开场动画diy
相信大家都想把自己的QQ空间装扮的漂漂亮亮的,那么自定义一个开场动画是分不开的,本文就教大家怎样自定义QQ空间开场动画。首先提醒大家的是:自定义QQ空间开场动画必须是黄钻三级以上。具体制作步骤如下:1、 打开QQ空间2、 点击装扮,
如何设置毕业论文的自定义格式样式及应用格式 毕业论文样式
如何设置毕业论文的自定义格式样式及应用格式——简介毕业论文是对大学学习的一份总结,都希望为自己的大学生活画上完美的句号,提交一份优秀的毕业论文。一份优秀的毕业论文是以规范的格式为前提的,所以在编写论文时,需要先按照学校的规
修改开机画面自定义开机画面 开机画面修改
修改开机画面(自定义开机画面)——简介自定义开机画面。让自己的电脑登录界面看起来更符合自己的要求。修改开机画面(自定义开机画面)——工具/原料logonui.exe修改开机画面(自定义开机画面)——方法 1 软件修改修改开机画面(自定义开机画