什么是拦截器
 

拦截器Interceptor…..拦截器是Struts的概念,它与过滤器是类似的…可以近似于看作是过滤器

为什么我们要使用拦截器

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

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

再次回顾拦截器基础

在开始讲解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>
               <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这个接口了。

编写拦截器类

public class MyInterceptor implements Interceptor {    @Override    public void destroy() {    }    @Override    public void init() {    }    @Override    public String intercept(ActionInvocation actionInvocation) throws Exception {        return null;    }}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;    }
   @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>

       <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;    }}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;
   }
}
public class TestAction extends ActionSupport {    public TestAction() {        System.out.println("我是Action类,我被初始化了!");    }    @Override    public String execute() throws Exception {        System.out.println("我是Action类的执行方法");        return null;    }}class TestAction extends ActionSupport {

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

   @Override
   public String execute() throws Exception {

       System.out.println("我是Action类的执行方法");


       return null;

   }
}

效果

Struts2【拦截器】_Struts 这里写图片描述

从效果图我们可以看出,他们的执行顺序是这样的:

其实很好理解,之前我们使用Struts为我们提供数据自动封装功能的时候,是这样子的:

Struts2【拦截器】_Struts_02 这里写图片描述
拦截器应用案例

需求:当用户登陆成功,跳转到显示用户的JSP页面中。当用户登陆失败,重新返回登陆界面。如果用户直接访问显示用户的JSP页面,那么返回到登陆界面

Struts2【拦截器】_Struts_03 这里写图片描述

分析

实现这个需求,我们可以使用过滤器的。只要获取用户的请求URL,再判断URL是不是为list.jsp,如果是,我们返回到登陆的界面就好了。

现在,为了对拦截器的理解,我们使用拦截器去完成这个功能!


搭建配置环境

Struts2【拦截器】_Struts_04 这里写图片描述 Struts2【拦截器】_Struts_05 这里写图片描述

编写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;    }}

/**
* 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;    }}

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();    }}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>
<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";    }}

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>
       <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();        }    }}

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>
<!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【拦截器】_Struts_06 这里写图片描述
Struts2其他拦截器

计时拦截器

Struts2自带了计时拦截器,也就是用来统计每个Action执行的时间

执行等待拦截器

如果页面执行得太慢了,Struts2还提供了执行等待拦截器,也就是说,当页面加载得太久了,就跳转到对应的提示页面…当服务器执行完毕了,也跳转到相对应的页面

Struts2防止表单重复提交拦截器

回顾防止表单重复提交

当我们学习Session的时候已经通过Session来编写了一个防止表单重复提交的小程序了,我们来回顾一下我们当时是怎么做的:

我们以前写表达重复提交就花了这么几个步骤…如果有兴趣的同学可以看一下以前的实现思路: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【拦截器】_Struts_07 这里写图片描述

为了熟悉一下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("登陆失败了!");        }    }}

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);    }}

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

   }
}

开发步骤

<%@ 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>
<%@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();    }
   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();
   }
<%--  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>
<%@ 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>
    public String updatePage() throws Exception {        //得到用户带过来的id,根据id查找对象       User user222 = service.findUser(user.getId());        ActionContext.getContext().getValueStack().push(user222);        return "updatePage";    }

       //得到用户带过来的id,根据id查找对象
      User user222 = service.findUser(user.getId());

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

       return "updatePage";
   }
<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>
   <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我们提供的防止表单重复提交的功能把!

Struts2【拦截器】_Struts_08 这里写图片描述

在需要提交的表单上使用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>
       <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>
<!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>
Struts2【拦截器】_Struts_09 这里写图片描述

测试

Struts2【拦截器】_Struts_10 这里写图片描述

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y