由自定义的拦截器窥探struts2 Interceptor拦截器拦截机制

来源:互联网 发布:unity3d 象棋 编辑:程序博客网 时间:2024/06/13 08:08


示例如下:

Action类:TestAction.java

package action;import com.opensymphony.xwork2.ActionSupport;public class TestAction extends ActionSupport {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String execute() throws Exception {// TODO Auto-generated method stubSystem.out.println("execute metod");System.out.println(name);return super.execute();//即 return SUCCESS;}}


自定义的拦截器1 :TestInterceptor1.java

package interceptor;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;public class TestInterceptor1 extends AbstractInterceptor {@Overridepublic String intercept(ActionInvocation invocation) throws Exception {System.out.println("interceptor1 拦截Action前");String result = invocation.invoke();System.out.println("interceptor1 拦截Action后");return result;}}


自定义的拦截器2:TestInterceptor2.java

package interceptor;import com.opensymphony.xwork2.ActionInvocation;import com.opensymphony.xwork2.interceptor.AbstractInterceptor;public class TestInterceptor2 extends AbstractInterceptor {@Overridepublic String intercept(ActionInvocation invocation) throws Exception {System.out.println("interceptor2 拦截Action前");String result = invocation.invoke();System.out.println("interceptor2 拦截Action后");return result;}}


struts.xml

<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"    "http://struts.apache.org/dtds/struts-2.0.dtd"><struts><constant name="struts.devMode" value="true"/><package name="default" extends="struts-default"><interceptors><!-- 配置自定义的拦截器 --><interceptor name="interceptor1" class="interceptor.TestInterceptor1"/><interceptor name="interceptor2" class="interceptor.TestInterceptor2"/></interceptors><action name="test" class="action.TestAction"><result>/welcome.jsp</result><interceptor-ref name="defaultStack"/><interceptor-ref name="interceptor1"/><interceptor-ref name="interceptor2"/></action></package></struts>


成功处理结果welcome.jsp文件:

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">        <title>My JSP 'welcome.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">-->  </head>    <body>    This is welcome page!success!. <br>  </body></html>



默认首页:index.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@ taglib prefix="s" uri="/struts-tags" %><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">        <title>My JSP 'index.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">-->  </head>    <body>    This is index page. <br>  </body></html>

部署文件web.xml

<?xml version="1.0" encoding="UTF-8"?><web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  <display-name></display-name>  <filter>        <filter-name>struts2</filter-name>        <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>    </filter>    <filter-mapping>        <filter-name>struts2</filter-name>        <url-pattern>/*</url-pattern>    </filter-mapping>    <welcome-file-list>    <welcome-file>index.jsp</welcome-file>  </welcome-file-list></web-app>


测试:

浏览器地址栏中输入:

http://localhost:8080/projectname/test?name=myname

后台console输出:

interceptor1 拦截Action前interceptor2 拦截Action前execute metodwninterceptor2 拦截Action后interceptor1 拦截Action后



结论:有上述示例可见,struts2的interceptor在action的方法执行前和执行后 都进行拦截。  在action的方法执行前,先配置的先拦截,后配置的后拦截;在action的方法执行后,后配置的先拦截,先配置的后拦截。拦截机制设计的很巧妙。


拦截方式struts的官方图:




请关注interceptor类中的intercept(ActionInvocation invocation)中的ActionInvocation类型的参数invocation,它是由struts2自动填充的,包含了被拦截的action的引用,可以通过调用该参数的invoke()方法,将控制器转交给下一个拦截器,或者转交给action的execute()方法(参照示例的测试结果)。

ActionInvocation是Struts2中的调度器,所以事实上,这些代码的调度执行,是在ActionInvocation的实现类中完成的,这里,我抽取了DefaultActionInvocation中的invoke()方法,它将向我们展示一切。 

附DefaultActionInvocation的invoke()的源码:

/** * @throws ConfigurationException If no result can be found with the returned code */public String invoke() throws Exception {    String profileKey = "invoke: ";    try {    UtilTimerStack.push(profileKey);        if (executed) {    throw new IllegalStateException("Action has already executed");    }        // 依次调用拦截器堆栈中的拦截器代码执行    if (interceptors.hasNext()) {    final InterceptorMapping interceptor = (InterceptorMapping) interceptors.next();    UtilTimerStack.profile("interceptor: "+interceptor.getName(),     new UtilTimerStack.ProfilingBlock<String>() {public String doProfiling() throws Exception {                         // 将ActionInvocation作为参数,调用interceptor中的intercept方法执行    resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);    return null;}    });    } else {    resultCode = invokeActionOnly();    }    // this is needed because the result will be executed, then control will return to the Interceptor, which will    // return above and flow through again    if (!executed) {            // 执行PreResultListener    if (preResultListeners != null) {    for (Iterator iterator = preResultListeners.iterator();    iterator.hasNext();) {    PreResultListener listener = (PreResultListener) iterator.next();        String _profileKey="preResultListener: ";    try {    UtilTimerStack.push(_profileKey);    listener.beforeResult(this, resultCode);    }    finally {    UtilTimerStack.pop(_profileKey);    }    }    }    // now execute the result, if we're supposed to            // action与interceptor执行完毕,执行Result    if (proxy.getExecuteResult()) {    executeResult();    }    executed = true;    }    return resultCode;    }    finally {    UtilTimerStack.pop(profileKey);    }}