以前便了解过,Struts 2的核心控制器是一个Filter过滤器,负责拦截全部的用户请求,当用户请求发送过来时,会去检测struts.xml是否存在这个action,若是存在,服务器便会自动帮咱们跳转到指定的处理类中去处理用户的请求,基本流程以下:html
该流程笔者理解是基本流程,。若是有不对的地方,请下方留言。我会改正。谢谢;java
好,接着往下讲:apache
注意:在struts.xml中,配置文件必须有该请求的处理类才能正常跳转,同时,返回SUCCESS字符串的类,必须继承ActionSupport,若是你没有继承,那么就返回"success",一样可以跳转到jsp逻辑视图,可是必须确保你struts.xml有<result name="success">xx.jsp</result>,该标签,具体操做在上一篇文章有介绍过简单例子。服务器
1.一、了解拦截器jsp
什么是拦截器,它的做用是什么?ide
拦截器,实际上就是对调用方法的改进。测试
做用:动态拦截对Action对象的调用,它提供了一种机制可使开发者能够定义在一个action执行的先后执行的代码,也能够在一个action执行前阻止其执行。同时也是提供了一种能够提取action中可重用的部分的方式。ui
拦截器的执行顺序:this
在执行Action的execute方法以前,Struts2会首先执行在struts.xml中引用的拦截器,在执行完全部引用的拦截器的intercept方法后,会执行Action的execute方法。 spa
新建一个类继承AbstractInterceptor。
package com.Interceptor; import java.util.Date; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.AbstractInterceptor; public class MyInterceptor extends AbstractInterceptor { private String name;//该属性与struts.xml中的<param name="name">简单拦截器</param>一致,也就是说该name的值是简单拦截器 public void setName(String name) { this.name = name; } //拦截action请求 @Override public String intercept(ActionInvocation arg0) throws Exception { //取得被拦截的action LoginAction action = (LoginAction)arg0.getAction(); System.out.println(name+":拦截器的动做------"+"开始执行登陆action的时间为:"+new Date()); long start = System.currentTimeMillis(); /* * ActionInvocation.invoke()就是通知struts2接着干下面的事情 * 好比 调用下一个拦截器 或 执行下一个Action * 就等于退出了你本身编写的这个interceptor了 * 在这里是去调用action的execute方法,也就是继续执行Struts2 接下来的方法*/ String result = arg0.invoke(); System.out.println(name+":拦截器的动做------"+"执行完登陆action的时间为:"+new Date()); long end = System.currentTimeMillis(); System.out.println(name+":拦截器的动做------"+"执行完该action的时间为:"+(end-start)+"毫秒"); System.out.println(result); //输出的值是:success return result; } } /** * 该页面的效果以下: * 简单拦截器:拦截器的动做------开始执行登陆action的时间为:Mon Oct 24 19:06:17 CST 2016 用户名:admin,密码:123 简单拦截器:拦截器的动做------执行完登陆action的时间为:Mon Oct 24 19:06:18 CST 2016 简单拦截器:拦截器的动做------执行完该action的时间为:1130毫秒 success * */
在struts.xml中配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <!--简单的拦截器 --> <package name="Interceptor" extends="struts-default" namespace="/ac"> <!-- 跳转前拦截 --> <interceptors> <!-- 声明简单的过滤器 --> <interceptor name="Inter" class="com.Interceptor.MyInterceptor"> <!--传递name的参数 --> <param name="name">简单拦截器</param> </interceptor> </interceptors> <action name="loginaction" class="com.Interceptor.LoginAction"> <result name="success">/Interceptor/welcome.jsp</result> <result name="input">/Interceptor/error.jsp</result> <!--注意:若是不加默认的拦截器的话,那么类型转换不会执行,也就是说不会把文本上的值赋值给实体类 --> <interceptor-ref name="defaultStack"/> <!-- 简单的过滤器,定义在这里告诉拦截器在此处action执行 --> <interceptor-ref name="Inter"> </interceptor-ref> </action> </package> </struts>
struts.xml解析:
<interceptors>:表示声明拦截器
<interceptor>: 表示定义一个拦截器
<param>:给该拦截器一个参数,属性为name
<interceptor-ref name="">:表示该拦截器在这个action中使用。
新建LoginAction类,继承ActionSupport
package com.Interceptor; import com.opensymphony.xwork2.ActionSupport; //action类处理 public class LoginAction extends ActionSupport { private String username; private String pwd; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } //默认执行execute方法 public String execute(){ System.out.println("用户名:"+username+",密码:"+pwd); return SUCCESS; }
新建jsp视图界面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>简单的登陆拦截</title> </head> <body> <!--若是在struts.xml中,package包中有配置namespace的话,那么在此处就应该配置。否则会报404错误 --> <s:form action="loginaction" namespace="/ac"> <s:textfield label="User Name" name="username"/> <s:password label="Password" name="pwd" /> <s:submit/> </s:form> </body> </html>
(代码笔者测试没问题)
拦截器不只能够定义多个拦截,还能够指定拦截特定的方法。
struts.xml的配置
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <!--简单的拦截器 --> <package name="Interceptor" extends="struts-default" namespace="/ac"> <!-- 跳转前拦截 --> <interceptors> <!-- 声明方法过滤器 --> <interceptor name="myMethod" class="com.Interceptor.MyMethodInterceptor"> <param name="name">方法过滤拦截器</param> </interceptor> </interceptors> <action name="loginaction" class="com.Interceptor.LoginAction" method="method1"> <!-- 若是是拦截方法的话,改成method="method2" --> <result name="success">/Interceptor/welcome.jsp</result> <!-- /Interceptor是笔者文件夹。别弄错了--> <result name="input">/Interceptor/error.jsp</result> <!--注意:若是不加默认的拦截器的话,那么类型转换不会执行,也就是说不会把文本上的值赋值给实体类 --> <interceptor-ref name="defaultStack"/> <!-- 方法过滤器 --> <interceptor-ref name="myMethod"> <param name="name">更名后的方法过滤器</param> <param name="includeMethods">method1,method3</param> <!--表示该方法不被拦截--> <param name="excludeMethods">method2</param> <!--表示该方法被拦截 --> </interceptor-ref> </action> </package> </struts>
修改LoginAction类
package com.Interceptor; import com.opensymphony.xwork2.ActionSupport; //action类处理 public class LoginAction extends ActionSupport { private String username; private String pwd; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; } // 过滤的方法 public String method1() throws Exception { System.out.println("Action执行方法:method1()"); return SUCCESS; } public String method2() throws Exception { System.out.println("Action执行方法:method2()"); return SUCCESS; } public String method3() throws Exception { System.out.println("Action执行方法:method3()"); return SUCCESS; } }
新建MyMethodInterceptor类继承MethodFilterInterceptor
MethodFilterInterceptor类表示你定义的拦截器支持方法过滤。
package com.Interceptor; import java.util.Date; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; //过滤方法 public class MyMethodInterceptor extends MethodFilterInterceptor { private String name; public void setName(String name) { this.name = name; } @Override protected String doIntercept(ActionInvocation arg0) throws Exception { //取得被拦截的action LoginAction action = (LoginAction)arg0.getAction(); System.out.println(name+":拦截器的动做------"+"开始执行登陆action的时间为:"+new Date()); long start = System.currentTimeMillis(); String result = arg0.invoke(); System.out.println(name+":拦截器的动做------"+"执行完登陆action的时间为:"+new Date()); long end = System.currentTimeMillis(); System.out.println(name+":拦截器的动做------"+"执行完该action的时间为:"+(end-start)+"毫秒"); System.out.println(result); //输出的值是:success return result; } }
至于jsp视图,同样,不须要改变。
获得的结果能够看出来:
当method="method1"或者是method="method3"的时候,会自动去执行MyMethodInterceptor 的方法doIntercept,而后跳转到welcome.jsp界面。
当method="method2"的时候,控制台会出现 Action执行方法:method2(),以后便被拦截了。
以上就是拦截方法的基本代码,例子很简单,可是重在理解。
可能笔者疑惑,为何须要过滤方法呢?由于拦截器它会自动拦截全部的方法,回形成资源的损耗,因此有些方法咱们能够指定不被拦截。
在拦截器中,execute方法执行以前或者以后的方法都被拦截在intercept方法中,这些的结构不够明白,咱们能够定义监听,虽然好像没什么用,可是了解一下也挺不错的。
实现拦截器的监听结果必须实现PreResultListener接口。
package com.Interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.PreResultListener; //过拦截器配置一个监听器 public class MyPreResultListener implements PreResultListener { //定义处理Result以前的行为 @Override public void beforeResult(ActionInvocation arg0, String arg1) { System.out.println("返回的逻辑视图为:"+arg1); } }
而后MyMethodInterceptor类修改成:
package com.Interceptor; import java.util.Date; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor; //过滤方法 public class MyMethodInterceptor extends MethodFilterInterceptor { private String name; public void setName(String name) { this.name = name; } @Override protected String doIntercept(ActionInvocation arg0) throws Exception { //将一个拦截结果的监听器注册给拦截器 arg0.addPreResultListener(new MyPreResultListener()); System.out.println("execute方法被调用以前的拦截"); //调用下一个拦截器或者action的执行方法 String result = arg0.invoke(); System.out.println("execute方法被调用以后的拦截"); return result; } }
以上就是拦截器基本知识,若是有错误的地方,请指正。谢谢。