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


示例如下:

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;
	}

	@Override
	public String execute() throws Exception {
		// TODO Auto-generated method stub
		System.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 {


	@Override
	public 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 {


	@Override
	public 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 metod
wn
interceptor2 拦截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);
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值