Struts2拦截器实现原理的理解

本文详细解读了Struts2框架中拦截器的工作原理,包括其动态拦截Action调用的过程、作用以及如何通过实现Interceptor接口来定制拦截逻辑。通过一个简单示例展示了拦截器如何在Action执行前后进行操作,并形成了特定的执行流程。

一.Struts2(MVC框架)

原理图:


二.Struts2拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行。同时也是提供了一种可以提取action中可重用的部分的方式。我们可以从上面的原理图中看出,Struts2拦截器在Action前执行和返回result后的操作,流程是:Interceptor1 2 3  Action Result(返回) Interceptor 3 2 1(逆序执行一遍
再来看看Struts2的拦截器执行源码:

(DefaultActionInvocation.java)

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();
                String interceptorMsg = "interceptor: " + interceptor.getName();
                UtilTimerStack.push(interceptorMsg);
                try {
			   //执行Interceptor拦截器里的intercept(ActionInvocation invocation)
                                resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);
                            }
                finally {
                    UtilTimerStack.pop(interceptorMsg);
                }
            } else {
	    //拦截器栈没有拦截器,则直接执行Action
                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) {
                if (preResultListeners != null) {
                    for (Object preResultListener : preResultListeners) {
                        PreResultListener listener = (PreResultListener) preResultListener;

                        String _profileKey = "preResultListener: ";
                        try {
                            UtilTimerStack.push(_profileKey);
                            listener.beforeResult(this, resultCode);
                        }
                        finally {
                            UtilTimerStack.pop(_profileKey);
                        }
                    }
                }

                // now execute the result, if we're supposed to
                if (proxy.getExecuteResult()) {
                    executeResult();
                }

                executed = true;
            }

            return resultCode;
        }
        finally {
            UtilTimerStack.pop(profileKey);
        }
    }

    public String invokeActionOnly() throws Exception {
        return invokeAction(getAction(), proxy.getConfig());
    }



(Interceptor接口的定义)

public interface Interceptor extends Serializable {

    /**
     * Called to let an interceptor clean up any resources it has allocated.
     */
    void destroy();

    /**
     * Called after an interceptor is created, but before any requests are processed using
     * {@link #intercept(com.opensymphony.xwork2.ActionInvocation) intercept} , giving
     * the Interceptor a chance to initialize any needed resources.
     */
    void init();

    /**
     * Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the
     * request by the {@link ActionInvocation} or to short-circuit the processing and just return a String return code.
     *
     * @param invocation the action invocation
     * @return the return code, either returned from {@link ActionInvocation#invoke()}, or from the interceptor itself.
     * @throws Exception any system-level error, as defined in {@link com.opensymphony.xwork2.Action#execute()}.
     */
    String intercept(ActionInvocation invocation) throws Exception;

}
再来一个简单的实例源码:

public class MyInterceptor implements Interceptor {

	public void destroy() {
		// TODO Auto-generated method stub

	}

	public void init() {
		// TODO Auto-generated method stub

	}

	public String intercept(ActionInvocation invocation) throws Exception {
		// TODO Auto-generated method stub
		System.out.println("interceptor");
		String result = invocation.invoke();
		System.out.println("finshed");
		return result;
	}

}
我们可以看到:intercept方法里再次调用了ActionInvocation的invoke方法,这就相当与一个递归调用,也就实现了一系列拦截器前操作(如:System.out.println("interceptor");)的先执行,等到递归返回resultCode时逆序执行后操作(如:System.out.println("finshed");),故形成了流程图所展示的情况


(以上只是我的个人理解  有不对请指正和探讨 O(∩_∩)O)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值