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