tags: Struts2


What is an interceptor

The Interceptor Interceptor… Interceptors are a Struts concept that is similar to filters… It can be approximated as a filter

Why do we use interceptors

Struts implements a lot of functions, such as automatic data encapsulation. File upload function…. Struts provides all of this functionality via interceptors……

  • Data is automatically encapsulated<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>This interceptor.
  • File upload approved<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>This interceptor

Interceptor design is based on component design application!

Review the interceptor basics again

The struts-default. XML file, described at the beginning of the Struts tutorial, defines all the interceptors for Struts. ** Because we load this file automatically when we start the server, we can use the functionality provided by Struts in the Action.

As many as 32 interceptors are defined in Struts-default. XML, and struts 2 provides interceptor stack definitions for easy reference.


            <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>
                <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>
Copy the code

In other words: when we want to reference more than one interceptor, we simply put all interceptors on the stack and reference the interceptor outside!

Note that Struts2 executes the default interceptor stack by default. Once the user has specified which interceptors to execute, the default interceptor stack is not executed!


Custom interceptors

Struts2 allows us to customize interceptors, which gives us more flexibility with the Struts2 framework!

Struts2 provides the Interceptor interface, and as long as we implement this interface, it is considered a custom Interceptor.

Of course, most of the time, we define interceptors by inheriting AbstractInterceptor from the class…. To learn more about interceptors, we’ll implement the Interceptor interface.

Write interceptor classes

  • When implementing this interface, there are three methods we need to implement:


public class MyInterceptor implements Interceptor {
    @Override
    public void destroy(a) {}@Override
    public void init(a) {}@Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        return null; }}Copy the code

Init () and destory() are methods that depend on the order in which interceptors are executed, so we’ll ignore…. for now Intercept is an intercept method


    / * * *@paramActionInvocation Execution status */
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        
        // Invoke the invoke() method, which permits the execution of the next interceptor or, if none is left, the business code for the Action
        actionInvocation.invoke();
        return null;
    }
Copy the code

This easily reminds us of the doFilter() method in learning filters, which is pretty much the same!


Configuration in struts.xml

Like the Struts default interceptor, our custom interceptor needs to be configured in Struts.

Since we configured a custom interceptor, the struts default interceptor stack will not execute. If we want to use the functionality of the default interceptor stack, we have to configure it in our own stack!


    <package name="xxx" extends="struts-default" >
        
        <interceptors>
            <! -- Configure user-defined interceptor -->
            <interceptor name="MyInterceptor" class="TestAction"/>
            
            <! -- Custom interceptor stack, we configure the custom interceptor stack, the default interceptor stack will not be executed, therefore, to use the default interceptor function, you need to configure it -->
            <interceptor-stack name="mystack">
                <! -- Reference the default interceptor stack, always on the first line -->
                <interceptor-ref name="defalutStack"/>
                
                <! -- Reference custom interceptor -->
                <interceptor-ref name="MyInterceptor"/>
            </interceptor-stack>
        </interceptors>
        
        <! Interceptor stack configured but not executed... Configure the execution interceptor -->
        <default-interceptor-ref name="mystack"/>
        
        <action name="TestAction" class="TestAction" method="execute">
            <result name="success">/index.jsp</result>

        </action>


    </package>
Copy the code

Order of execution of interceptors

Let’s look at the order in which interceptors and Action classes are executed… Just print it to the console on the corresponding method!

  • The interceptor

public class MyInterceptor implements Interceptor {
    @Override
    public void destroy(a) {

        System.out.println("I am the destruction method for interceptors.");

    }

    @Override
    public void init(a) {

        System.out.println("I'm the initialization method for the interceptor.");
    }


    / * * *@paramActionInvocation Execution status */
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {

        System.out.println("I am the interceptor method.");

        // Invoke the invoke() method, which permits the execution of the next interceptor or, if none is left, the business code for the Action
        // The doFilter() method can be considered as a filter
        actionInvocation.invoke();
        return null; }}Copy the code
  • The Action class

public class TestAction extends ActionSupport {

    public TestAction(a) {
        System.out.println("I'm the Action class, I'm initialized!");
    }

    @Override
    public String execute(a) throws Exception {

        System.out.println("I'm the execution method of the Action class.");


        return null; }}Copy the code

The effect

From the renderings, we can see that they are implemented in this order:

  • When the server is turned on, the interceptor’s init() method is executed
  • When an Action is accessed, an Action instance is created
  • Once the Action instance is created, the interceptor’s () method is called
  • Finally, execute() on the Action

When we used Struts to provide automatic data encapsulation, it looked like this:

  • The server starts and loads the configuration file information
  • Initialize the default interceptor stack
  • When a user accesses an Action, an instance of the Action is created. Get Action details [member variables, setters and getters]
  • Execute the interceptor specific content and encapsulate the Web side data to the Action based on the Action specific information
  • Finally, execute() will get the encapsulated data!


Interceptor application case

Requirement: When the user logs in successfully, jump to the JSP page showing the user. If the login fails, the user returns to the login page. If the user accesses the JSP page that displays the user directly, return to the login screen

Analysis of the

To implement this requirement, we can use filters. Just get the user’s request URL and determine if the URL is list.jsp. If so, we return to the login interface.

Now, for the sake of understanding interceptors, we use interceptors to do this!


Setting up the Configuration Environment

  • Import our c3P0.xml file
  • Import the C3P0 development package
  • Import the mysql development package
  • Write the database connection pool utility class
  • DbUtils development kit
  • Eight development kits for Struts2

  • Create database tables and import data

Write the entity


package zhongfucheng.entity;

/** * Created by ozc on 2017/5/3. */
public class User {
    
    
    private String id ;
    private String username;
    private String cellphone;
    private String email;
    private String password;

    public String getId(a) {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername(a) {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getCellphone(a) {
        return cellphone;
    }

    public void setCellphone(String cellphone) {
        this.cellphone = cellphone;
    }

    public String getEmail(a) {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPassword(a) {
        return password;
    }

    public void setPassword(String password) {
        this.password = password; }}Copy the code

Write the DAO

package zhongfucheng.dao;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import zhongfucheng.entity.User;
import zhongfucheng.utils.Utils2DB;

import java.sql.SQLException;
import java.util.List;

/** * Created by ozc on 2017/5/3. */
public class UserDao {

    public User login(User user) {

        try {
            String sql = "SELECT * FROM user WHERE username = ? AND password = ?";
            QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
            return (User) queryRunner.query(sql, new BeanHandler(User.class), new Object[]{user.getUsername(), user.getPassword()});
        } catch (SQLException e) {
            new RuntimeException("Landing failed!");
        }

        return null;
    }

    public List<User> getAll(a) {

        try {
            String sql = "SELECT * FROM user";
            QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());
            return (List<User>) queryRunner.query(sql, new BeanListHandler(User.class));
        } catch (SQLException e) {
            new RuntimeException("Landing failed!");
        }

        return null; }}Copy the code

Write the Service


public class Service {

    UserDao userDao = new UserDao();

    public User login(User user) {
        return userDao.login(user);

    }

    public List<User> getAll(a) {
        returnuserDao.getAll(); }}Copy the code

Write the login JSP page


<% @ page contentType="text/html; charset=UTF-8" language="java"% >
<html>
<head>
    <title>Landing page</title>
</head>
<body>

<form action="${pageContext.request.contextPath}/user_login" method="post">
    <input type="text" name="username"><br>
    <input type="password" name="password"><br>
    <input type="submit" value="Login"><br>
</form>
</body>
</html>

Copy the code

Write the Action that handles the request


package zhongfucheng.action;

import com.opensymphony.xwork2.ActionContext;
import zhongfucheng.entity.User;
import zhongfucheng.service.Service;

import java.util.List;
import java.util.Map;

/** * Created by ozc on 2017/5/3. */
public class UserAction {


    /****************1. Encapsulate data ********************/
    private User user;

    public User getUser(a) {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    / * * * * * * * * * * * * * * * 2. Call the Service * * * * * * * * * * * * * * * * * * * /
    Service service = new Service();


    / / login
    public String login(a) {

        User user = service.login(this.user);

        if (user == null) {
            return "input";
        } else {
            // Store user information in the Session domain object
            Map<String, Object> session = ActionContext.getContext().getSession();
            session.put("user", user);


            // Successful login
            return "login"; }}// Query user information
    public String list(a) {

        // Get all user information
        List<User> users = service.getAll();

        // Save to the request domain object
        Map<String, Object> request = ActionContext.getContext().getContextMap();

        request.put("users", users);

        return "list"; }}Copy the code

Struts. XML configuration file

    <package name="xxx" extends="struts-default" >
        <action name="user_*" class="zhongfucheng.action.UserAction" method="{1}" >

            <! If login succeeds, redirect to Action and execute the list business method.
            <result name="login" type="redirectAction">user_list</result>

            <! -- If it is a list, go to list.jsp -->
            <result name="list" >/WEB-INF/list.jsp</result>
        </action>

    </package>

Copy the code

So far, we can get the user’s specific information…. if we log in or not This is unreasonable

What we want is to view specific user information only if the user is calling the login method, or if the user is already logged in.

Therefore, we need to intercept them and jump to the corresponding display page only when the user invokes the login method or is already logged in


The interceptor


package zhongfucheng;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;

/** * Created by ozc on 2017/5/3. */
public class Interceptor  extends AbstractInterceptor{


    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {

        // Get the proxy object being executed
        ActionProxy proxy = actionInvocation.getProxy();

        // Get the executing method from the proxy object
        String method = proxy.getMethod();


        // If the method name is not login, return them to the login page
        if(! method.equals("login")) {

            // Check whether the user is logged in
            Object user = ActionContext.getContext().getSession().get("user");

            // If you are not logged in, return to the login page
            if (user == null) {

                return "input";
            } else {

                // If logged in, then send it to the specific user information page
                returnactionInvocation.invoke(); }}else {

            // If you are accessing the login method, let it execute
            returnactionInvocation.invoke(); }}}Copy the code

Struts.xml


<?xml version="1.0" encoding="UTF-8" ? >

      

<struts>
    <package name="xxx" extends="struts-default">

        <interceptors>
            <! -- Configure custom interceptor -->
            <interceptor name="Interceptor1" class="zhongfucheng.Interceptor"/>

            <! Configure the interceptor stack and load the default interceptor stack into the custom interceptor stack.
            <interceptor-stack name="myStack">
                <interceptor-ref name="Interceptor1"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>

        </interceptors>


        <! Struts interceptor -->

        <! Acntion in the current package executes the myStack stack.
        <default-interceptor-ref name="myStack"></default-interceptor-ref>


        <! -- The second way: MyStack <interceptor-ref name="defaultStackt"></interceptor-ref> <interceptor-ref name="loginCheck"></interceptor-ref> -->

        <! -- Execute user stack (same as execute custom stack in current aciton)
        <! -- <interceptor-ref name="myStack"></interceptor-ref>-->

        <action name="user_*" class="zhongfucheng.action.UserAction" method="{1}">

            <! If login succeeds, redirect to Action and execute the list business method.
            <result name="login" type="redirectAction">user_list</result>

            <! -- If it is a list, go to list.jsp -->
            <result name="list">/WEB-INF/list.jsp</result>


            <! Return to the login page if you are accessing Action directly or no user has logged in.
            <result name="input">/login.jsp</result>

        </action>


    </package>
</struts>

Copy the code

Effect:

Only when the user logs in can you view the details of the user


Struts2 other interceptors

## Struts2 comes with a timer interceptor, which counts the execution time of each Action

Execute wait for interceptor ##

Struts2 also provides an execution-wait interceptor if the page is too slow, which means that when the page takes too long to load, it jumps to the corresponding prompt page… When the server completes execution, it also jumps to the corresponding page

If you find this article helpful, give the author a little encouragement