拦截器基础
Posted 专注改变人生。
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拦截器基础相关的知识,希望对你有一定的参考价值。
二、自定义拦截器应用
2.1 第一个自定义拦截器
- index.jsp
<body> <a href="<%=path%>/Interceptor/InterceptorAction">此页面跳转的action会被自定义拦截器拦截</a> </body>
- struts.xml
<package name="default" namespace="/Interceptor" extends="struts-default"> <!-- 定义拦截器 --> <interceptors> <interceptor name="interceptorTest" class="interceptor.InterceptorTest"></interceptor> </interceptors> <action name="InterceptorAction" class="action.InterceptorAction"> <result name="re">/index_2.jsp</result> <!-- 引用拦截器 --> <interceptor-ref name="interceptorTest"></interceptor-ref> </action> </package>
- InterceptorTest.java(编写拦截器的代码)
package interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; /** * 自定义的拦截器 * @author Administrator * */ public class InterceptorTest implements Interceptor { public void destroy() { } public void init() { } public String intercept(ActionInvocation actionInterceptor) throws Exception { System.out.println("我是第一次自定义拦截器"); /* * 让Action的方法执行,并返回action的结果。 * ActionInvocation。invoke()方法会调用下一个拦截器 或 执行下一个Action,如果是执行actino就返回action的result值。 * 而ActionInvocation。getResultCode()只获得action的result返回值并不执行action。 */ String next=actionInterceptor.invoke(); return null; } }
- InterceptorAction.java(被拦截的action)
package action; public class InterceptorAction { public String execute(){ System.out.println("我是action"); return "re"; } }
- index_2.jsp(action执行成功后跳转的页面)
<body>
我是跳转后的页面
</body>
结果:
查看后台可知,拦截器中的方法比action的方法先执行,说明拦截成功。
2.2 拦截器栈:如果拦截器很多的话,可以把这些拦截器放到拦截器栈里,在action类中引用拦截器栈,拦截器栈中的每个拦截器会按顺序对action进行拦截。
如上例,再加一个拦截器。
- struts.xml
<package name="default" namespace="/Interceptor" extends="struts-default"> <!-- 定义拦截器 --> <interceptors> <interceptor name="interceptorTest" class="interceptor.InterceptorTest"></interceptor> <interceptor name="interceptor_two" class="interceptor.Interceptor_two"></interceptor> <!-- 定义拦截器栈,引入拦截器 --> <interceptor-stack name="mystack"> <interceptor-ref name="interceptor_two"></interceptor-ref> <interceptor-ref name="interceptorTest"></interceptor-ref> </interceptor-stack> </interceptors> <action name="InterceptorAction" class="action.InterceptorAction"> <result name="re">/index_2.jsp</result> <!-- 引用拦截器栈--> <interceptor-ref name="mystack"></interceptor-ref> </action> </package>
- 解析:当访问url为"/工程名/Interceptor/InterceptorAction"这个action 的时候,此时这个action里引用了拦截器栈,拦截器栈里有两个拦截器,会按顺序逐一地对action进行拦截
2.3 默认拦截器
- struts.xml
<package name="default" namespace="/Interceptor" extends="struts-default"> <!-- 定义拦截器 --> <interceptors> <interceptor name="interceptorTest" class="interceptor.InterceptorTest"></interceptor> <interceptor name="interceptor_two" class="interceptor.Interceptor_two"></interceptor> <!-- 设定哪一个拦截器或者拦截器栈为默认的 1:当Action中没有使用interceptor-ref引用时,默认拦截器将会起作用。如果Action中配置interceptor-ref,那么 默认的拦截器将不起作用 2:将设定default-interceptor-ref为自定义的拦截器后,struts-default.xml中定义的默认拦截器将不起作用。 所有Struts的功能将不能使用。要将defaultStack拦截器栈引用到自定义到拦截器栈中 3:其他的package要使用自定义的拦截器,将package做一个继承即可。 --> <interceptor-stack name="mystack"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="interceptor_two"></interceptor-ref> <interceptor-ref name="interceptorTest"></interceptor-ref> </interceptor-stack> </interceptors> <default-interceptor-ref name="mystack"></default-interceptor-ref> <action name="InterceptorAction" class="action.InterceptorAction"> <result name="re">/index_2.jsp</result> </action> </package>
1:当Action中没有使用interceptor-ref引用时,默认拦截器将会起作用。如果Action中配置interceptor-ref,那么
默认的拦截器将不起作用
2:将设定default-interceptor-ref为自定义的拦截器后,struts-default.xml中定义的默认拦截器将不起作用。
所有Struts的功能将不能使用。要将defaultStack拦截器栈引用到自定义到拦截器栈中。
3:其他的package要使用自定义的拦截器,将package做一个继承即可。
4. Struts2在struts-default包中定义了一个默认的拦截器栈引用:defaultStack。因此当我们定义的包继承自struts-default包时也继承了它的默认拦截器引用:defaultStack,当我们不为Action显式的应用拦截器,则defaultStack栈会起作用。
2.4 用自定义拦截器实现登录验证
-
servlet里用过滤器实现登录验证,而struts2可以用拦截器来实现登录验证,但是在开发中,一般使用过滤器来实现登录验证,因为拦截器只能拦截action。
- index.jsp
<body> <h2>登录系统</h2> <form action="interceptor/main" method="post"> 用户名:<s:textfield name="username"></s:textfield><br/> 密 码:<s:password name="password"></s:password> <s:submit value="提交"></s:submit> </form> </body>
- sturts.xml(如果没有<interceptor-ref name="defaultStack"></interceptor-ref>的话,那么在action中就无法得到表单的值,这个功能是默认拦截器引用:defaultStack的功能之一)
<package name="default" namespace="/interceptor" extends="struts-default"> <interceptors > <interceptor name="login" class="interceptor.LoginInterceptor"></interceptor> </interceptors> <action name="main" class="action.GoMainAction"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="login"></interceptor-ref> <result name="main">/index_2.jsp</result> </action> </package>
- GoMainAction.java
package action; import javax.servlet.http.HttpSession; import org.omg.CORBA.Request; import com.opensymphony.xwork2.ActionSupport; import actionUtil.BaseAction; public class GoMainAction extends BaseAction{ /* * 在action中获取表单值的前提是必须在struts.xml中引用默认拦截器引用:defaultStack */ private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String execute(){ if((this.username).equals("admin")){ if((this.password).equals("123")){ HttpSession session=request.getSession(); session.setAttribute("login", "ok"); return "main"; }else{ System.out.println("密码错误"); return null; } }else{ System.out.println("用户名错误"); return null; } } }
-
LoginInterceptor.java
package interceptor; import java.io.PrintWriter; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; import com.opensymphony.xwork2.util.ValueStack; import action.GoMainAction; public class LoginInterceptor implements Interceptor{ public void destroy() { } public void init() { } public String intercept(ActionInvocation actionInvocation) throws Exception { Object action=actionInvocation.getAction(); //拿到被拦截的action对象 ActionContext context=actionInvocation.getInvocationContext(); //拿到action的广义值栈。 HttpServletRequest request=ServletActionContext.getRequest(); //拿到request对象 HttpServletResponse response = ServletActionContext.getResponse(); //拿到response对象 Map<String,Object> sessionMap=context.getSession(); // ValueStack valuestack=context.getValueStack(); //拿到action的狭义值栈。 if(action.getClass().equals(GoMainAction.class)){ //如果是验证登录的action,。则不进行拦截 actionInvocation.invoke(); return null; }else{ response.setContentType("text/html"); PrintWriter out = response.getWriter(); String loginURL = request.getContextPath() + "/index.jsp"; out.println("<script language=\'javascript\'>"); out.println("window.alert(\'您还未登录,或者登录已超时,请重新登录\');"); out.println("window.location.href = \'" + loginURL + "\';"); out.println("</script>"); return null; } } }
- index_2.jsp
<body>
登录成功
</body>
- 用拦截器实现登录验证的问题: 1. 只能拦截action而无法拦截页面,也就是说无法拦截未登录用户访问需要登录的页面。
2.5 利用拦截器实现监听程序运行效率(监听每个方法的运行时间,时间越长代表效率越低)
- index.jsp
<body> <a href="interceptor/TestAction!one">方法1的运行效率</a> <a href="interceptor/TestAction!two">方法2的运行效率</a> </body>
- struts.xml
<package name="default" namespace="/interceptor" extends="struts-default"> <interceptors> <interceptor name="test" class="interceptor.TestInterceptor"></interceptor> </interceptors> <action name="TestAction" class="action.TestAction"> <interceptor-ref name="defaultStack"></interceptor-ref> <interceptor-ref name="test"></interceptor-ref> </action> </package>
-
TestAction.java
package action; public class TestAction { public String execute(){ return null; } /** * 要测试的方法1 * @return */ public String one(){ System.out.println("运行one方法"); return null; } /** * 要测试的方法2 * @return */ public String two(){ System.out.println("运行two方法"); try { Thread.sleep(6000); //停留6秒 } catch (InterruptedException e) { e.printStackTrace(); } return null; } }
- TestInterceptor.java(拦截器)
package interceptor; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; import com.opensymphony.xwork2.util.ValueStack; public class TestInterceptor implements Interceptor{ public void destroy() { } public void init() { } public String intercept(ActionInvocation actionInvocation) throws Exception { Object obj=actionInvocation.getAction(); //获取正在拦截的对象 ActionContext actionContext=actionInvocation.getInvocationContext(); //获取被拦截action的上下文对象 ValueStack valuestack=actionContext.getValueStack(); //获取action的狭义值栈 HttpServletRequest request = ServletActionContext.getRequest(); //获取erquest对象 StringBuffer requestURL=request.getRequestURL(); //获取超时方法的URL //让action方法执行,并测试 long start=System.currentTimeMillis(); //获取方法执行前的时间 actionInvocation.invoke(); //执行方法 long end=System.currentTimeMillis(); //获取方法执行后的时间 int diffSecond = (int) ((end - start) / 1000); //获取方法总共执行时间差 if(diffSecond >5){ System.out.println("requestURI= " + requestURL +",间隔时间= "+diffSecond); //如果方法执行时间超过5秒就把这个URL打印出来 } return null; } }
结果:
- 如结果,这样我们就把那些运行了很久的方法找了出来。
以上是关于拦截器基础的主要内容,如果未能解决你的问题,请参考以下文章
[vscode]--HTML代码片段(基础版,reactvuejquery)
AOP框架Dora.Interception 3.0 [3]: 拦截器设计