Interceptor (interceptor)
1, Interceptor overview
- Interceptor is one of the most powerful features of struts 2. It is a mechanism that allows users to do some processing before Action execution and after Result execution.
- Interceptors are conceptually the same as servlet filters or JDK proxy classes. Interceptors allow for crosscutting, separating action from framework. You can use the interceptor to do the following:
- Provide preprocessing logic before calling action.
- Provide post-processing logic after calling action.
- Catch exceptions so that standby processing can be performed.
- Many functions provided in struts 2 framework are implemented by interceptors, including exception handling, file upload, life cycle callback and validation. In fact, since struts 2 bases most of its functionality on interceptors, it's unlikely to assign seven or eight interceptors to each action.
2, Advantages of interceptors
- Simplify the implementation of Action. The interceptor can separate many functions from Action, which greatly reduces the code of Action.
- Each interceptor has its own unique function.
- The general code is modularized, and the general code in the Action is extracted and encapsulated in the interceptor.
- Improve the reusability. When the general code is encapsulated in the interceptor and the code is modularized, different actions can be configured according to different functions.
- AOP is implemented. Struts 2 implements AOP (aspect oriented programming) through interceptors. AOP is a programming paradigm, and it is a programming method that focuses on functions.
3, Predefined interceptors
- In the previous example, we can see that their properties have values before the execute method of Action is run, and these values are the same as the parameters in the user's request, indicating that the values are put into the properties of Action before the execution of an Action. This function is operated by an interceptor.
- Many interceptors are defined in struts 2, which are in struts default package in struts-default.xml file
<interceptors> <interceptor name="alias" class="com.opensymphony.xwork2.interceptor.AliasInterceptor"/> <interceptor name="autowiring" class="com.opensymphony.xwork2.spring.interceptor.ActionAutowiringInterceptor"/> <interceptor name="chain" class="com.opensymphony.xwork2.interceptor.ChainingInterceptor"/> <interceptor name="conversionError" class="org.apache.struts2.interceptor.StrutsConversionErrorInterceptor"/> <interceptor name="cookie" class="org.apache.struts2.interceptor.CookieInterceptor"/> <interceptor name="cookieProvider" class="org.apache.struts2.interceptor.CookieProviderInterceptor"/> <interceptor name="clearSession" class="org.apache.struts2.interceptor.ClearSessionInterceptor" /> <interceptor name="createSession" class="org.apache.struts2.interceptor.CreateSessionInterceptor" /> <interceptor name="debugging" class="org.apache.struts2.interceptor.debugging.DebuggingInterceptor" /> <interceptor name="execAndWait" class="org.apache.struts2.interceptor.ExecuteAndWaitInterceptor"/> <interceptor name="exception" class="com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor"/> <interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/> <interceptor name="i18n" class="org.apache.struts2.interceptor.I18nInterceptor"/> <interceptor name="logger" class="com.opensymphony.xwork2.interceptor.LoggingInterceptor"/> <interceptor name="modelDriven" class="com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor"/> <interceptor name="scopedModelDriven" class="com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor"/> <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> <interceptor name="paramRemover" class="com.opensymphony.xwork2.interceptor.ParameterRemoverInterceptor"/> <interceptor name="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInterceptor"/> <interceptor name="prepare" class="com.opensymphony.xwork2.interceptor.PrepareInterceptor"/> <interceptor name="staticParams" class="com.opensymphony.xwork2.interceptor.StaticParametersInterceptor"/> <interceptor name="scope" class="org.apache.struts2.interceptor.ScopeInterceptor"/> <interceptor name="servletConfig" class="org.apache.struts2.interceptor.ServletConfigInterceptor"/> <interceptor name="timer" class="com.opensymphony.xwork2.interceptor.TimerInterceptor"/> <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/> <interceptor name="tokenSession" class="org.apache.struts2.interceptor.TokenSessionStoreInterceptor"/> <interceptor name="validation" class="org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor"/> <interceptor name="workflow" class="com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor"/> <interceptor name="store" class="org.apache.struts2.interceptor.MessageStoreInterceptor" /> <interceptor name="checkbox" class="org.apache.struts2.interceptor.CheckboxInterceptor" /> <interceptor name="datetime" class="org.apache.struts2.interceptor.DateTextFieldInterceptor" /> <interceptor name="profiling" class="org.apache.struts2.interceptor.ProfilingActivationInterceptor" /> <interceptor name="roles" class="org.apache.struts2.interceptor.RolesInterceptor" /> <interceptor name="annotationWorkflow" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationWorkflowInterceptor" /> <interceptor name="annotationParameterFilter" class="com.opensymphony.xwork2.interceptor.annotations.AnnotationParameterFilterInterceptor" /> <interceptor name="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" /> <interceptor name="noop" class="org.apache.struts2.interceptor.NoOpInterceptor" /> </interceptors>
- Next, we will introduce some commonly used interceptors
Serial number | Interceptor | Explain |
---|---|---|
1 | alias | Allow parameters to use different aliases between requests. |
2 | checkbox | Assist in managing the check boxes by adding a parameter value of false to the unchecked check boxes. |
3 | conversionError | Error messages that convert strings to parameter types are placed in the error field of the action. |
4 | createSession | Automatically create an HTTP session if it does not already exist. |
5 | debugging | Provides developers with several different debug screens. |
6 | execAndWait | When the action is executed in the background, the user is sent to the waiting page in the middle. |
7 | exception | Map exceptions thrown from action to result, allowing automatic handling of exceptions by redirection. |
8 | fileUpload | Easy to upload. |
9 | i18n | Tracks the selected area during a user session. |
10 | logger | Provide simple logging by outputting the name of the action being performed. |
11 | params | Set request parameters on action. |
12 | prepare | This is often used to perform preprocessing, such as setting up a database connection. |
13 | profile | Allows you to record simple analysis information for an action. |
14 | scope | Stores and retrieves the status of an action within the scope of a session or application. |
15 | ServletConfig | Provides access to a variety of servlet based action s. |
16 | timer | Provide simple analysis information in the form of action execution time. |
17 | token | Check the validity of the action to prevent the form from being submitted repeatedly. |
18 | validation | Provide authentication support for action. |
19 | staticParams | Set the Action parameter defined in the configuration file to the corresponding Action instance. The Action parameter uses the < param > tag and is a child element of < Action >. If the value set in the configuration file and the name of the requested value are the same, the requested value shall prevail. When initializing the Action, the parameters in struts.xml will be mapped to the Action properties, and then the data requested by the user will be set to the corresponding properties in the Action instance. |
20 | modelDriven | r if Action implements the ModelDriven interface, it stores the model object obtained by getModel() method into OnglValueStack |
21 | chain | Set the Action property of the previous end of execution to the current Action. He is used in the Action of the result specified by the ResultType chain. The Action object of the result will get the properties corresponding to the previous Action from the value stack. He realizes the data transfer between actions. |
Predefined interceptor stack
- When we use struts.xml, do we see any code about interceptors?
- Although the user does not actively configure the interceptor, struts 2 will use the default interceptor
- The declarations and references of these interceptors are in the struts-default.xml file. The definition of interceptors has been written before. Here, only the defaultStack interceptors of their interceptors are listed. They are all placed in the struts default package under the same package. The interceptor stack is defined as a direct child of < interceptors >.
<interceptors> <interceptor-stack name="defaultStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="servletConfig"/> <interceptor-ref name="i18n"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="scopedModelDriven"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="datetime"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="debugging"/> </interceptor-stack> </interceptors>
- Reference interceptor stack
<package name="struts-default" abstract="true" strict-method-invocation="true"> <default-interceptor-ref name="defaultStack"/> </package>
The above configuration can be divided into four parts
-
<interceptor>
-
<interceptor-stack>
-
<interceptor-ref>
-
<default-interceptor-ref>
Configuration and use of predefined interceptors
In the Action configuration of struts.xml, reference the interceptor to be used
- In the action element, how to use the < perception ref > child element? In fact, it's very simple. You only need to configure the required < interceptor ref > sub element in the < action > element, and configure the name of the interceptor to be used in the < interceptor ref > sub element, for example:
<action name="interceptor1" class=""> <param name="name">taeyeon</param> <result></result> <interceptor-ref name="chainStack"></interceptor-ref> <interceptor-ref name="chain"></interceptor-ref> </action>
- < interceptor ref > the name of the child element can be not only the name of a defined interceptor, but also the name of a defined interceptor stack. The above name="chainStack" is an interceptor stack.
- In fact, a < default interceptor ref name = "defaultstack" / > has been defined in the extended struts default package when configuring your own package. It is this definition. In the previous example, the user did not take the initiative to configure the interceptor, but we still used the functions in the interceptor, which the user did not know.
The order in which interceptors are called
- First, find out the reference of the interceptor that he declares himself, that is, whether the < action > element has the < interceptor ref > child element.
- Second, check whether the package containing the < action > has a reference to declare the default interceptor. That is, the < default interceptor ref > child element of the < package > element.
- Finally, recursively look for the parent package of the package to see if the default interceptor reference is declared until the interceptor reference is found.
These three relationships are actually coverage relationships. When they are owned at the same time, the interceptor references in the lowest < action > package will cover other relationships.
Custom interceptor
What is a custom interceptor
- The so-called custom interceptor is defined and implemented by the user, not defined by struts 2.
- Sometimes in the actual development, we need to use a custom interceptor to implement specific functions for us.
Develop a custom interceptor
- To implement a custom Interceptor is very simple, just write a class that implements the Interceptor interface, which is defined as:
public interface Interceptor extends Serializable { void destroy(); void init(); String intercept(ActionInvocation invocation) throws Exception;
- The intercept() method is the processing method of the interceptor, and the functions to be implemented by the user are mainly written in this method.
- After the intercept() method, write invocation.invoke();, which means to continue to run the interceptor for subsequent processing. If the interceptor, it will continue to run until the Action, and then execute the Result.
- If the invocation.invoke(); is not written, it means that the execution ends at the present time, and no further backward execution will be carried out. In other words, the subsequent interceptors and actions will not be executed. Instead, return the Result string here and run the Result directly.
- The function written before the sentence "invocation.invoke();" will be executed before the Action runs.
- The function written after the sentence "invocation.invoke();" will be executed after the Result is run.
- The return value of the intercept method is the final Result character set to be returned, which is only valid when the Result is not executed before, that is, there is no invocation.invoke(); in this sentence, the return value is equivalent to the final Result string to be returned, and then the corresponding Result processing is performed.
Example
- Write Action processing class, here we just output statement, and write actual function code in actual development
package struts2.com.interceptor; import com.opensymphony.xwork2.ActionSupport; public class InterceptorAction extends ActionSupport { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String execute() throws Exception { System.out.println(name); System.out.println("I am Action"); return SUCCESS; } }
- Writing Interceptor
package struts2.com.interceptor; import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.interceptor.Interceptor; public class Interceptor_1 implements Interceptor { @Override public void destroy() { System.out.println("I was destroyed"); } @Override public void init() { System.out.println("I'm initialized"); } @Override public String intercept(ActionInvocation invocation) throws Exception { System.out.println("I am here Action Previous implementation"); invocation.invoke(); System.out.println("I am here Result After execution"); return null; } }
- Configure xml file
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.5//EN" "http://struts.apache.org/dtds/struts-2.5.dtd"> <struts> <package name="interceptor" extends="struts-default"> <interceptors> <interceptor name="myinterceptor" class="struts2.com.interceptor.Interceptor_1"/> <interceptor-stack name="mystack"> <interceptor-ref name="myinterceptor"/> </interceptor-stack> </interceptors> <action name="interceptor1" class="struts2.com.interceptor.InterceptorAction"> <result>lastinterpetor.jsp</result> <interceptor-ref name="mystack"/> <interceptor-ref name="defaultStack"/> </action> </package> </struts>
Now that we have implemented the Interceptor interface, we are equivalent to customizing an Interceptor. Then we need to declare and define the Interceptor in the referenced package. For example, the child element of the above < interceptors > element is to declare the Interceptor and define the Interceptor stack; then we can use it in < action > < interceptor ref name = "mystack" / > to reference interceptors; if other interceptors are referenced here, then the default interceptor stack in the inherited package will not take effect, because it is the default, so when there is a value, the default interceptor stack will not be used, so we want to use the functions in it, we can only refer to it again through < interceptor ref name ="defaultStack"/> 4. Write the submission and response page
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>interceptor Submission</title> </head> <body> <form action="interceptor1.action"> //Name: < input type = "text" name = "name" > <input type="submit" value="Submission"> </form> </body> </html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="s" uri="/struts-tags" %> <html> <head> <title>interpetor After submission</title> </head> <body> helloword! <s:property value="name"/> <% System.out.println("I am Result"); %> </body> </html>
If the default interceptor is not used in the xml configuration, the value of the name attribute here cannot be passed to the value stack. You can't get the value if you get the page 5. Console output
....... I'm initialized December 24, 2019 2:48:59 PM org.apache.coyote.AbstractProtocol start Information: Starting ProtocolHandler ["http-bio-80"] I execute before Action Jay Chou I am Action. I am Result. I execute after Result
From the output of the console, we can see that the output statement written in the init method of the interceptor will be initialized when the server starts, and the number of times of the initialized output is determined by the number of references to the interceptor in the xml file, for example, if the interceptor 2 is referenced in the xml file, then the init method will be called when the server starts It is used twice; the one written before the method is executed before the Action is run, and then it is run to the invocation.invoke(); it is executed by the Action or other interceptors; the code after the method is executed after the Result is executed. 6. Be sure to note that if the interceptor does not write the invocation.invoke(); method, then the code behind the method will not be executed, and even the Action and other interceptors will not be executed, and the return string will be returned directly to the Result to match the Result and run the Result. Also remember that the execution position of the interceptor is before the Action starts and after the Result is executed.
Parameters in interceptor
- We also need to pass some parameters to the Interceptor at some time, such as
- Interceptor parameters configured in the action element of xml
output<action name="paraminterceptor" class="struts2.com.interceptor.InterceptorAction"> <result>lastinterpetor.jsp</result> <interceptor-ref name="defaultStack"/> <interceptor-ref name="myinterceptor" > <param name="age">123</param> </interceptor-ref>
The name attribute value of param element should correspond to the attribute value in interceptorMy age: 123
- Setting parameters when the interceptor is declared
output<interceptors> <interceptor name="myinterceptor" class="struts2.com.interceptor.Interceptor_1"> <param name="213"></param> </interceptor> <interceptor-stack name="mystack"> <interceptor-ref name="myinterceptor"/> </interceptor-stack> </interceptors>
The parameters of the interceptor are children of < interceptor ref >.My age: 321
- When both cases are configured, let's see if we use that parameter.
We can see that if the two places are configured, they are mainly based on the interceptor configuration parameters in the action element. We can also add parameters when referencing in the interceptor stack.My age: 123