Struts2【拦截器】就是这么简单

什么是拦截器

拦截器Interceptor.....拦截器是Struts的概念,它与过滤器是相似的...能够近似于看做是过滤器php

为何咱们要使用拦截器

前面在介绍Struts的时候已经讲解过了,Struts为咱们实现了不少的功能,好比数据自动封装阿..文件上传功能阿....Struts为咱们提供的这些功能都是经过拦截器完成的......html

  • 数据自动封装经过<interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/>这个拦截器。
  • 文件上传经过<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>这个拦截器

拦截器的设计就是基于组件设计的应用java

再次回顾拦截器基础

在开始讲解Struts的时候已经说明过了struts-default.xml这个文件,它**定义了Struts的全部拦截器。**由于咱们在启动服务器的时候会自动装载这个文件,所以咱们才能够在Action中使用到Struts为咱们提供的功能【数据自动封装...文件上传】mysql

在struts-default.xml中定义的拦截器就有32个之多,Struts2为了方便咱们对拦截器的引用,提供了拦截器栈的定义。web

<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>
复制代码

也就是说:当咱们要引用多个拦截器的时候,只要把拦截器都放在栈里头,在外边引用拦截器便可!sql

值得注意的是:Struts2默认执行的是默认拦截器栈,一旦用户有指定执行哪些拦截器,那么默认的拦截器栈就不会被执行!数据库


自定义拦截器

Struts2容许咱们自定义拦截器,这就使咱们可以更加灵活地操做Struts2这个框架了!apache

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了,因此不搭理用户的请求

咱们之前写表达重复提交就花了这么几个步骤...若是有兴趣的同窗能够看一下之前的实现思路:blog.csdn.net/hon_3y/arti…


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页面把

这里写图片描述

测试

这里写图片描述

若是文章有错的地方欢迎指正,你们互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同窗,能够关注微信公众号:Java3y

相关文章
相关标签/搜索