SSH Development Model - Struts 2 (Section 2)

The last section has learned how to build the development environment of Struts 2. In this blog, we continue to go deep into Struts 2 and learn about the interceptor of Struts 2 framework.

Firstly, we analyze the source code of the filter configured in the web.xml file.
In the StrutsPrepareAndExecuteFilter source code, there is an init() method that calls the method to get a Dispatcher object, which is the key to our analysis. Enter its source code and call the init_TraditionalXmlConfigurations() method in its init() method. The source code of this method is as follows:

    private void init_TraditionalXmlConfigurations() {
        String configPaths = initParams.get("config");
        if (configPaths == null) {
            configPaths = DEFAULT_CONFIGURATION_PATHS;
        String[] files = configPaths.split("\\s*[,]\\s*");
        for (String file : files) {
            if (file.endsWith(".xml")) {
                if ("xwork.xml".equals(file)) {
                    configurationManager.addContainerProvider(createXmlConfigurationProvider(file, false));
                } else {
                    configurationManager.addContainerProvider(createStrutsXmlConfigurationProvider(file, false, servletContext));
            } else {
                throw new IllegalArgumentException("Invalid configuration file name");

Note that there is such a code in this method, configPaths = DEFAULT_CONFIGURATION_PATHS; the key is this field, we will follow up.

    private static final String DEFAULT_CONFIGURATION_PATHS = "struts-default.xml,struts-plugin.xml,struts.xml";

See here, you must understand why the name of the new struts 2 configuration file must be struts.xml? Why does the package tag in struts2's configuration file inherit struts-default? I believe I should not have to explain.

Actually, there are many functions of filters, which have been introduced before, but if all the tasks are handed over to the filters, the burden of the filters will be very heavy, the code of the filters will be very large, which is not in line with our low-coupling, high cohesion design ideas.

We assume that to implement a function, we divide it into several steps in a class.

class aa{
    Step 1:
    Step 2:
    Step 3:
    Step 4:

But now we design and implement it like this.

class a1{
    Step 1:
class a2{
    Step 2:
class a3{
    Step 3:
class a4{
    Step 4:

Each class only implements one step, and then directly calls the methods of the four classes.
What's the advantage of this? These four steps will not affect each other, and you can easily invoke a single step. This is the idea of separation of concerns. The problem to be dealt with is accomplished by one class, each class only completes one function. Such a class is called an interceptor.
What's the difference between an interceptor and a filter?
The same thing: they all act as interceptors.
Difference: Filter is the standard of J2EE, any program can be used.
Interceptor is the standard of struts2 framework. It can't leave struts2 framework. It must depend on struts2 framework.
The filter intercepts the web.xml configuration file, and other interception tasks are handed over to the interceptor.
The order of execution is filter execution first, interceptor execution later.

Many interceptors are defined in the struts-default.xml file.

    interceptors:Definition struts2 Frame interceptor
    *name:The name of the interceptor is unique
    *class:Interceptor corresponding Action Complete path of class
            <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="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="com.opensymphony.xwork2.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="actionMappingParams" class="org.apache.struts2.interceptor.ActionMappingParametersInteceptor"/>
            <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="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="multiselect" class="org.apache.struts2.interceptor.MultiselectInterceptor" />

There are many interceptors, among which there are many keywords we are familiar with, such as cookie, params, i18n and so on.
Under the definition of interceptor, many interceptor-stack tags are defined. These tags define the interceptor stack. What role do they play?
Here I just post a default interceptor stack for explanation.

     interceptor-stack:interceptor stack
        *The interceptor stack is equivalent to the interceptor stack defined above. list Collection, where interceptors are stored in sequence
        //Execution in the order of declarations
            <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="multiselect"/>
                <interceptor-ref name="staticParams"/>
                <interceptor-ref name="actionMappingParams"/>
                <interceptor-ref name="params">
                    <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
                <interceptor-ref name="conversionError"/>
                <interceptor-ref name="validation">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                <interceptor-ref name="workflow">
                    <param name="excludeMethods">input,back,cancel,browse</param>
                <interceptor-ref name="debugging"/>

As for whether it really has the order of execution? I will not take you to verify, you can find a few interceptors, and then hit the breakpoint in the corresponding class, and then run the validation.

It should be noted that the default Stack interceptor stack is the default execution of the program by default. Does anyone wonder why the default execution of the program is the default Stack, because its name is defaultStack, so it will be executed? Obviously, there is a reason. We read the source code down and found a configuration: <default-interceptor-ref name="defaultStack"/>, which is used to configure the interceptor stack for default execution.
The interceptor is introduced here first.
Previously, it was an introduction to Struts 2 framework. There are many places you may not understand, because in order to let you quickly understand the framework, we did not introduce it in a deeper level, but just described the tip of the iceberg. Next, we will study the Struts 2 framework systematically. Please look forward to it.

Tags: Java Apache Struts xml Spring

Posted on Sun, 25 Aug 2019 23:12:45 -0700 by cityguru