Java programmers go from stupid birds to cainiao (forty-six) to discuss the implementation principle and source code analysis of struts2 (8) interceptor

Source: Internet
Author: User

This article is from: Cao shenghuan blog column. Reprinted please indicate the source:Http://blog.csdn.net/csh624366188

 

Interceptor is one of struts2's most powerful features. It can also be said to be the core of struts2. It allows you to process the action or result before or after it is executed. At the same time, the interceptor allows you to modularize common code and use it as a reusable class. Many features of struts2 are implemented by the interceptor. Interception is an implementation policy of AOP. In the Chinese documents of webwork, the interceptor is the object for dynamically intercepting action calls. It provides a mechanism for developers to define the code to be executed before and after an action is executed, or to prevent it from being executed before an action is executed. It also provides a way to extract reusable parts of an action. When talking about interceptor, we should also know the interceptor chain, which is called the interceptor stack in struts 2 ). The interceptor chain is to link the interceptor into a chain in a certain order. When accessing intercepted methods or fields, the interceptor in the interceptor chain will be called in the order defined previously.

I. Implementation principle of interceptor:

Most of the time, the interceptor method is called by proxy. The interceptor Implementation of struts 2 is relatively simple. When a request arrives at the servletdispatcher of struts 2, Struts 2 searches for the configuration file, instantiates the relative interceptor object based on the configuration, and then Concatenates the object into a list ), finally, the interceptor in the list is called one by one. In fact, the reason why we can use the interceptor so flexibly is that,This is entirely due to the use of "dynamic proxy ".. Dynamic proxy is used to process proxy objects differently based on customer needs. For customers, you only need to know a proxy object. In struts2,How is the interceptor called through a dynamic proxy?? When an action request arrives, the system proxy generates an action proxy object, which calls the action's execute () or specified method and. search for the interceptor corresponding to the action in XML. If a corresponding interceptor exists, the interceptor is called before (after) The action method is executed. If no corresponding interceptor exists, the action method is executed. The system calls the interceptor through actioninvocation. The Code is as follows:

if (interceptors.hasNext()) {Interceptor interceptor=(Interceptor)interceptors.next();resultCode = interceptor.intercept(this);} else {if (proxy.getConfig().getMethodName() == null) {resultCode = getAction().execute();} else {resultCode = invokeAction(getAction(), proxy.getConfig());}}

It can be found that the action is not directly associated with the interceptor, but it is completely "agent" in the organization that the action works with the interceptor. For example:


2. Analyze the interceptor

We all know that the interceptor interface definition is nothing special. Except for the init and destory methods, the intercept method is the core method for implementing the entire interceptor mechanism. The parameter actioninvocation it depends on is the famous action scheduler. Let's take a look at a typical abstract implementation class of interceptor:

Public abstract class aroundinterceptor extends actinterceptor {/* (non-javadoc) * @ see COM. opensymphony. xwork2.interceptor. abstractinterceptor # intercept (COM. opensymphony. xwork2.actioninvocation) * // @ overridepublic string intercept (actioninvocation Invocation) throws exception {string result = NULL; before (Invocation); // call the next Interceptor. If the interceptor does not exist, then, execute action result = invocation. invoke (); after (invocation, result); return result;} public abstract void before (actioninvocation Invocation) throws exception; public abstract void after (actioninvocation invocation, string resultcode) throws exception ;}

In this implementation class, we have actually implemented the prototype of the simplest interceptor. It is worth noting that an important method is invocation. Invoke (). This is the method in actioninvocation, and actioninvocation is the action scheduler. Therefore, this method has the following two meanings:

1. If there are other interceptor in the interceptor stack, invocation. Invoke () will call the execution of the next interceptor in the stack.
2. If the interceptor stack contains only action, invocation. Invoke () will call the action for execution.


Therefore, we can find that the invocation. Invoke () method is actually the core of the entire interceptor framework. Based on this implementation mechanism, we can also get the following two very important inferences:
1. If we do not use invocation. Invoke () in the Interceptor to call the next element in the stack, but directly return a string as the execution result, the entire execution will be aborted.
2. we can use invocation. invoke () is the boundary. The code in the interceptor is divided into two parts, in invocation. the code before invoke () will be executed in sequence before the action, while the code before invocation. the code after invoke () will be executed in reverse order after the action.
Therefore, we can use invocation. Invoke () as the true interception point of the action code to implement AOP.

Iii. source code parsing


Next, let's look at the source code to see how struts2 ensures the execution sequence between the interceptor, action, and result. Previously, I mentioned that actioninvocation is the scheduler in struts2. In fact, the scheduling and execution of these codes are completed in the implementation class of actioninvocation. Here, I extracted the invoke () method from defaactionactioninvocation, which will show us everything.

 

/*** @ 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");} // call the interceptor code in the interceptor stack to execute if (interceptors. hasnext () {final interceptormapping interceptor = (interceptormapping) interc Eptors. next (); utiltimerstack. profile ("Interceptor:" + interceptor. getname (), new utiltimerstack. profilingblock <string> () {Public String doprofiling () throws exception {// use actioninvocation as a parameter and call the intercept method in Interceptor to execute resultcode = interceptor. getinterceptor (). intercept (defaactionactioninvocation. this); return NULL ;}}) ;}else {resultcode = invokeactiononly () ;}// this is needed because the re Sult will be executed, then control will return to the interceptor, which will // return abve and flow through again if (! Executed) {// execute preresultlistener if (preresultlisteners! = NULL) {for (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 and interceptor are finished, execute result if (proxy. getexecuteresult () {executeresult ();} executed = true;} return resultcode;} finally {utiltimerstack. pop (profilekey );}}

 

From the source code, we can see four different layers of the Action layer, which are reflected in this method. They are: Interceptor, action, preresultlistener, and result. This method ensures the orderly calling and execution of these layers. We can also see thatStruts2 has many considerations in the Action hierarchy design. Each layer has a high degree of scalability and insertion points, so that programmers can add their own implementation mechanisms at any level they like to change the action behavior.
Here, we need to emphasize the invocation of the interceptor part:

resultCode = interceptor.getInterceptor().intercept(DefaultActionInvocation.this);  


On the surface, it only executes the intercept method in the Interceptor. If we look at it with the interceptor, we can see the starting point:

Public String intercept (actioninvocation Invocation) throws exception {string result = NULL; before (Invocation); // call the invocation invoke () method, which forms a recursive call result = invocation. invoke (); after (invocation, result); return result ;}

Originally, the intercept () method recursively calls the invoke () method of actioninvocation. The actioninvocation loop is nested in intercept () until the execution of the statement result = invocation. Invoke () ends. In this way, interceptor will end the execution in reverse order according to the initial execution.An ordered linked list is converted into a stack execution process through recursive calls. The Code executed in an ordered sequence is converted into a code process in which two segments are executed in the opposite order, thus cleverly Implementing AOP.. This has become the AOP basis for the action layer of struts2.

 

In the next article, let's take a look at how to customize your Interceptor:

A detailed description of struts2 (9) built-in interceptor and custom Interceptor (with source code)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.