1. 程式人生 > 其它 >Struts2【攔截器】

Struts2【攔截器】

什麼是攔截器

攔截器Interceptor…..攔截器是Struts的概念,它與過濾器是類似的…可以近似於看作是過濾器

為什麼我們要使用攔截器

前面在介紹Struts的時候已經講解過了,Struts為我們實現了很多的功能,比如資料自動封裝阿..檔案上傳功能阿….Struts為我們提供的這些功能都是通過攔截器完成的……

  • 資料自動封裝通過<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>這個攔截器。
  • 檔案上傳通過<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
    這個攔截器

攔截器的設計就是基於元件設計的應用

再次回顧攔截器基礎

在開始講解Struts的時候已經說明過了struts-default.xml這個檔案,它定義了Struts的所有攔截器。因為我們在啟動伺服器的時候會自動裝載這個檔案,因此我們才可以在Action中使用到Struts為我們提供的功能【資料自動封裝…檔案上傳】

在struts-default.xml中定義的攔截器就有32個之多,Struts2為了方便我們對攔截器的引用,提供了攔截器棧的定義。

            <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>

也就是說:當我們要引用多個攔截器的時候,只要把攔截器都放在棧裡頭,在外邊引用攔截器即可!

值得注意的是:Struts2預設執行的是預設攔截器棧,一旦使用者有指定執行哪些攔截器,那麼預設的攔截器棧就不會被執行!


自定義攔截器

Struts2允許我們自定義攔截器,這就使我們能夠更加靈活地操作Struts2這個框架了!

Struts2提供了Interceptor這個攔截器介面,只要我們實現這個介面,那麼這就算是自定義開發攔截器了。

當然啦,大部分時候,我們定義攔截器都是繼承AbstractInterceptor這個類….為了學習攔截器的內容,下面就實現Interceptor這個介面了。

編寫攔截器類

  • 當實現該介面時,有3個需要我們實現的方法:
public class MyInterceptor implements Interceptor {
    @Override
    public void destroy() {

    }

    @Override
    public void init() {

    }

    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {
        return null;
    }
}

init()和destory()都是和攔截器執行順序有關的方法,我們現在先不理會….首先來講解intercept這個方法

    /**
     * @param actionInvocation 攔截器的執行狀態
     */
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {

        //呼叫invoke()方法,代表著放行執行下一個攔截器,如果沒有攔截器了,那麼就執行Action的業務程式碼
        actionInvocation.invoke();
        return null;
    }

這很容易就能讓我們想起在學習過濾器中的doFilter()方法,其實是差不多的!


在struts.xml中配置

像Struts預設的攔截器一樣,我們自定義的攔截器是需要我們在struts中配置的。

由於我們配置了自定義攔截器,那麼struts預設的攔截器棧是不會執行的。如果我們想要使用預設攔截器棧的功能,就必須把它配置在我們自定義的棧中!

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

        <interceptors>
            <!--配置使用者自定義的攔截器-->
            <interceptor name="MyInterceptor" class="TestAction"/>

            <!--自定義攔截器棧,我們配置了自定義的攔截器,預設的攔截器棧就不會被執行,因此,想要使用預設的攔截器功能,就要配置進來-->
            <interceptor-stack name="mystack">
                <!--引用預設的攔截器棧,一定要放在第一行-->
                <interceptor-ref name="defalutStack"/>

                <!--引用自定義的攔截器-->
                <interceptor-ref name="MyInterceptor"/>
            </interceptor-stack>
        </interceptors>

        <!--上面配置了攔截器棧,但是沒有被執行...下面配置執行攔截器-->
        <default-interceptor-ref name="mystack"/>

        <action name="TestAction" class="TestAction" method="execute">
            <result name="success">/index.jsp</result>

        </action>


    </package>

攔截器的執行順序

我們來觀察攔截器和Action類的執行順序…只要在對應的方法上向控制檯輸出就行了!

  • 攔截器
public class MyInterceptor implements Interceptor {
    @Override
    public void destroy() {

        System.out.println("我是攔截器的銷燬方法");

    }

    @Override
    public void init() {

        System.out.println("我是攔截器的初始化方法");
    }


    /**
     * @param actionInvocation 攔截器的執行狀態
     */
    @Override
    public String intercept(ActionInvocation actionInvocation) throws Exception {

        System.out.println("我是攔截器的攔截方法");

        //呼叫invoke()方法,代表著放行執行下一個攔截器,如果沒有攔截器了,那麼就執行Action的業務程式碼
        //可看成是過濾器的doFilter()方法
        actionInvocation.invoke();
        return null;
    }
}
  • Action類
public class TestAction extends ActionSupport {

    public TestAction() {
        System.out.println("我是Action類,我被初始化了!");
    }

    @Override
    public String execute() throws Exception {

        System.out.println("我是Action類的執行方法");


        return null;

    }
}

效果

這裡寫圖片描述

從效果圖我們可以看出,他們的執行順序是這樣的:

  • 當伺服器開啟的時候,會執行攔截器的init()方法
  • 當訪問Action時,Action例項被建立
  • 建立完Action例項,會呼叫攔截器的interceptor()方法
  • 最後,執行Action的execute()方法

其實很好理解,之前我們使用Struts為我們提供資料自動封裝功能的時候,是這樣子的:

  • 伺服器啟動,載入配置檔案的資訊
  • 初始化預設的攔截器棧
  • 當用戶訪問Action時,建立Action的例項。拿到Action具體的資訊【成員變數、setter和getter】
  • 執行攔截器具體的內容,根據Action具體的資訊,把web端的資料封裝到Action上
  • 最後在execute()就可以得到封裝後的資料了!

這裡寫圖片描述


攔截器應用案例

需求:當用戶登陸成功,跳轉到顯示使用者的JSP頁面中。當用戶登陸失敗,重新返回登陸介面。如果使用者直接訪問顯示使用者的JSP頁面,那麼返回到登陸介面

這裡寫圖片描述

分析

實現這個需求,我們可以使用過濾器的。只要獲取使用者的請求URL,再判斷URL是不是為list.jsp,如果是,我們返回到登陸的介面就好了。

現在,為了對攔截器的理解,我們使用攔截器去完成這個功能!


搭建配置環境

  • 匯入我們c3p0.xml檔案
  • 匯入c3p0開發包
  • 匯入mysql開發包
  • 寫資料庫連線池工具類
  • dbUtils開發包
  • 8個struts2需要用到的開發包

這裡寫圖片描述

  • 建立資料庫表,匯入資料

這裡寫圖片描述

編寫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() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    public String getCellphone() {
        return cellphone;
    }

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

    public String getEmail() {
        return email;
    }

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

    public String getPassword() {
        return password;
    }

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

編寫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("登陸失敗了!");
        }

        return null;
    }

    public List<User> getAll() {

        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("登陸失敗了!");
        }

        return null;
    }

}

編寫Service

public class Service {

    UserDao userDao = new UserDao();

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

    }

    public List<User> getAll() {
        return userDao.getAll();
    }
}

編寫登陸的JSP頁面

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登陸頁面</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="登陸"><br>
</form>
</body>
</html>

編寫處理請求的Action

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.封裝資料********************/
    private User user;

    public User getUser() {
        return user;
    }

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

    /***************2.呼叫Service*******************/
    Service service = new Service();


    //登陸
    public String login() {

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

        if (user == null) {
            return "input";
        } else {
            //將user的資訊存到Session域物件中
            Map<String, Object> session = ActionContext.getContext().getSession();
            session.put("user", user);


            //登陸成功
            return "login";
        }
    }

    //檢視user資訊
    public String list() {

        //拿到所有使用者的資訊
        List<User> users = service.getAll();

        //存到request域物件中
        Map<String, Object> request = ActionContext.getContext().getContextMap();

        request.put("users", users);

        return "list";
    }

}

struts.xml配置檔案

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

            <!--如果登陸成功,重定向到Action中,執行list業務方法-->
            <result name="login" type="redirectAction">user_list</result>

            <!--如果是list,那麼跳轉到list.jsp頁面-->
            <result name="list" >/WEB-INF/list.jsp</result>
        </action>

    </package>

到目前為止,我們登陸或者不登陸都可以得到使用者的具體資訊….這是不合理的

我們想要的效果是:只有使用者正在呼叫login方法,或者該使用者已經登陸了,才可以檢視具體的使用者資訊

因此,我們們要攔截它們,只有使用者呼叫的是login方法時或者已經登陸的情況下,才能跳轉到對應的顯示頁面


攔截器

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 {

        //得到正在執行的代理物件
        ActionProxy proxy = actionInvocation.getProxy();

        //通過代理物件得到正在執行的方法
        String method = proxy.getMethod();


        //如果方法的名字不是login,那麼就讓他們返回到login頁面上
        if (!method.equals("login")) {

            //檢視使用者是否登陸了
            Object user = ActionContext.getContext().getSession().get("user");

            //如果沒有登陸,回到login頁面
            if (user == null) {

                return "input";
            } else {

                //登陸了,那麼就讓它訪問具體的使用者資訊頁面
                return actionInvocation.invoke();
            }
        } else {

            //如果是訪問login方法,那麼就讓它執行
            return actionInvocation.invoke();
        }

    }
}

Struts.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

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

        <interceptors>
            <!--配置自定義的攔截器-->
            <interceptor name="Interceptor1" class="zhongfucheng.Interceptor"/>

            <!--配置攔截器棧,把預設的攔截器棧都載入自定義的攔截器棧中-->
            <interceptor-stack name="myStack">
                <interceptor-ref name="Interceptor1"/>
                <interceptor-ref name="defaultStack"/>
            </interceptor-stack>

        </interceptors>


        <!--讓Struts執行攔截器-->

        <!--【執行攔截器:第一種寫法: 當前包下所有的acntion都執行myStack棧】-->
        <default-interceptor-ref name="myStack"></default-interceptor-ref>


        <!--第二種寫法: 只是在這一個Action中執行myStack棧
        <interceptor-ref name="defaultStackt"></interceptor-ref>
        <interceptor-ref name="loginCheck"></interceptor-ref>
        -->

        <!-- 第三種寫法:執行使用者棧(與第二種寫法一樣, 只在當前aciton中執行自定義棧) -->
        <!-- <interceptor-ref name="myStack"></interceptor-ref>-->

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

            <!--如果登陸成功,重定向到Action中,執行list業務方法-->
            <result name="login" type="redirectAction">user_list</result>

            <!--如果是list,那麼跳轉到list.jsp頁面-->
            <result name="list">/WEB-INF/list.jsp</result>


            <!--如果是直接訪問Action或者沒有使用者登陸,返回login頁面-->
            <result name="input">/login.jsp</result>

        </action>


    </package>
</struts>

效果:

只有當用戶登陸了才能檢視使用者具體資訊,直接訪問Action會跳轉回

這裡寫圖片描述


Struts2其他攔截器

計時攔截器

Struts2自帶了計時攔截器,也就是用來統計每個Action執行的時間

執行等待攔截器

如果頁面執行得太慢了,Struts2還提供了執行等待攔截器,也就是說,當頁面載入得太久了,就跳轉到對應的提示頁面…當伺服器執行完畢了,也跳轉到相對應的頁面

Struts2防止表單重複提交攔截器

回顧防止表單重複提交

當我們學習Session的時候已經通過Session來編寫了一個防止表單重複提交的小程式了,我們來回顧一下我們當時是怎麼做的:

  • 在Servlet上生成獨一無二的token,儲存在Session域中,並交給JSP頁面
  • JSP頁面在提交表單資料的時候,把token放在隱藏域中…一起帶過去給Servlet
  • Servlet判斷使用者有沒有帶token值過來,判斷token的值是否和Session的相匹配
  • 如果使用者是第一次提交的話,那麼就允許使用者的請求,接著就把儲存在Session中的token值去除
  • 等使用者想要再次提交的時候,Servlet發現Session中並沒有token了,所以不搭理使用者的請求

我們以前寫表達重複提交就花了這麼幾個步驟…如果有興趣的同學可以看一下以前的實現思路:http://blog.csdn.net/hon_3y/article/details/54799494#t11


Struts2防止表單重複提交

Struts2是簡化我們的開發的,表單重複提交也是一件非常常用的功能…Struts2也為我們實現了…當然啦,也是通過攔截器來實現

   <interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>

它的實現原理和我們以前寫的思路幾乎一致…它不需要另外寫一個元件來生成token值,struts2標籤就有這麼一個功能…因此是十分方便的

這裡寫圖片描述

為了熟悉一下Struts2,我們也使用Struts2來編寫一下上圖的程式

編寫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 void add(User user) {
        try {

            String sql = "INSERT INTO user(id,username,cellphone,password,address) VALUES (?,?,?,?,?)";
            QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

            queryRunner.update(sql, new Object[]{user.getId(), user.getUsername(), user.getCellphone(), user.getPassword(),user.getAddress()});

        } catch (SQLException e) {
            new RuntimeException("登陸失敗了!");
        }
    }

    public User findUser(String id) {
        try {
            String sql = "SELECT * FROM user WHERE id=?";
            QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

            return (User) queryRunner.query(sql, new BeanHandler(User.class), new Object[]{id});

        } catch (SQLException e) {
            new RuntimeException("登陸失敗了!");
        }
        return null;
    }

    public List<User> getAll() {

        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("登陸失敗了!");
        }
        return null;
    }
    public void  updateUser(User user) {

        try {
            String sql = "UPDATE user SET username=?,password=?,cellphone=? WHERE id=?";
            QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

            queryRunner.update(sql, new Object[]{user.getUsername(), user.getPassword(), user.getCellphone(), user.getId()});
        } catch (SQLException e) {
            new RuntimeException("登陸失敗了!");
        }
    }

}

編寫service

package zhongfucheng.service;

import zhongfucheng.dao.UserDao;
import zhongfucheng.entity.User;
import zhongfucheng.utils.WebUtils;

import java.util.List;

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

    UserDao userDao = new UserDao();

    public void add(User user) {


        //手動設定id,因為在資料庫表我沒使用自動增長id
        user.setId(WebUtils.makeId());

        //這是以前的表,規定要address,只能手動設定了
        user.setAddress("廣州");
        userDao.add(user);

    }

    public User findUser(String id) {

        return userDao.findUser(id);

    }

    public List<User> getAll() {

        return userDao.getAll();

    }
    public void  updateUser(User user) {


        userDao.updateUser(user);

    }
}

開發步驟

  • 編寫新增使用者JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
</head>
<body>

<form action="${pageContext.request.contextPath}/user_register" method="post">
    <table border="1">

        <tr>
            <td>使用者名稱:<input type="text" name="username"></td>
        </tr>
        <tr>
            <td> 密碼:<input type="password" name="password"></td>
        </tr>
        <tr>
            <td>電話:<input type="text" name="cellphone"></td>
        </tr>
        <tr>
            <td><input type="submit" value="提交"></td>
        </tr>
    </table>
</form>


</body>
</html>
  • 使用了模型驅動封裝資料,新增使用者
    //這裡一定要例項化
    User user = new User();

    public User getUser() {
        return user;
    }

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

    @Override
    public User getModel() {
        return user;
    }


    /*******呼叫service********/
    Service service = new Service();

    public String register() throws Exception {

        service.add(user);


        //註冊成功,就跳轉到list()方法,list方法就跳轉到檢視所有使用者頁面了!
        return list();
    }
  • 列出全部的使用者資料,提供修改功能,需要把id傳遞過去,明確修改的是哪一個使用者
<%--
  Created by IntelliJ IDEA.
  User: ozc
  Date: 2017/5/2
  Time: 18:24
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<head>
    <title>列出下載頁面</title>
</head>
<body>
<table border="1" align="center">
    <tr>
        <td>使用者id</td>
        <td>使用者姓名</td>
        <td>使用者密碼</td>
        <td>使用者電話</td>
        <td>操作</td>
    </tr>

    <s:if test="#request.users!=null">
        <c:forEach items="${users}" var="user">
            <tr>
                <td>${user.id}</td>
                <td>${user.username}</td>
                <td>${user.password}</td>
                <td>${user.cellphone}</td>
                <td><a href="${pageContext.request.contextPath}/user_updatePage?id=${user.id}">修改</a></td>
            </tr>
        </c:forEach>
    </s:if>
</table>


</body>
</html>
  • Action得到web帶過來的id,找到物件,新增到值棧中(資料回顯)
    public String updatePage() throws Exception {

        //得到使用者帶過來的id,根據id查詢物件
       User user222 = service.findUser(user.getId());

        ActionContext.getContext().getValueStack().push(user222);

        return "updatePage";
    }
  • 修改使用者的JSP頁面,使用Struts2提供的回顯技術,並把id通過隱藏域帶過去給Action..最終是通過id來修改使用者的資料
<form action="${pageContext.request.contextPath}/user_update">
    <table border="1">

        <tr>
            <td>使用者名稱<s:textfield name="username"/></td>
        </tr>
        <tr>
            <td>密碼 <s:textfield name="password" /></td>
        </tr>
        <tr>
            <td>電話<s:textfield name="cellphone"/></td>
        </tr>
        <s:hidden name="id"/>

        <tr>
            <td><input type="submit" value="修改"></td>
        </tr>
    </table>
</form>

防止表單重複提交

上面我們已經完成了大部分的功能了,但當我們如果提交之後,再重新整理頁面,那麼表單的資料就會重複提交…我們使用Struts2我們提供的防止表單重複提交的功能把!

這裡寫圖片描述

在需要提交的表單上使用token標籤

<table border="1">
        <s:token></s:token>
        <tr>
            <td>使用者名稱:<input type="text" name="username"></td>
        </tr>
        <tr>
            <td> 密碼:<input type="password" name="password"></td>
        </tr>
        <tr>
            <td>電話:<input type="text" name="cellphone"></td>
        </tr>
        <tr>
            <td><input type="submit" value="提交"></td>
        </tr>
    </table>

在struts配置檔案中配置攔截器

token攔截器預設是不會啟動的,也就是說:需要我們手動配置

當我們配置攔截器的時候,Struts2預設的攔截器是不會執行的,所以要把Struts2預設的攔截器也寫上

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
        "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name="struts.ui.theme" value="simple"/>
    <package name="xxx" extends="struts-default">



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

            <interceptor-ref name="defaultStack"/>

            <interceptor-ref name="token">
                <!-- 要攔截的方法! -->
                <param name="includeMethods">register</param>
            </interceptor-ref>

            <!--如果是list,那麼就跳轉到list的JSP頁面-->
            <result name="list"> /list.jsp</result>

            <!--請求跳轉到修改頁面-->
            <result name="updatePage">/update.jsp</result>

            <!--如果校驗成功,跳轉到login.jsp頁面回顯-->
            <result name="success">/login.jsp</result>

            <result name="redirectList" type="redirect">/user_list</result>
        </action>
    </package>

    <include file="config.xml"/>

</struts>
  • 當我們重複提交的時候,它會報錯,因此,如果它報錯了,我們就跳轉到register頁面把

這裡寫圖片描述

測試

這裡寫圖片描述