拦截器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;
}
}
效果
这里写图片描述从效果图我们可以看出,他们的执行顺序是这样的:
其实很好理解,之前我们使用Struts为我们提供数据自动封装功能的时候,是这样子的:
这里写图片描述拦截器应用案例
需求:当用户登陆成功,跳转到显示用户的JSP页面中。当用户登陆失败,重新返回登陆界面。如果用户直接访问显示用户的JSP页面,那么返回到登陆界面
这里写图片描述分析
实现这个需求,我们可以使用过滤器的。只要获取用户的请求URL,再判断URL是不是为list.jsp,如果是,我们返回到登陆的界面就好了。
现在,为了对拦截器的理解,我们使用拦截器去完成这个功能!
搭建配置环境
这里写图片描述 这里写图片描述编写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其他拦截器
计时拦截器
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,我们也使用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我们提供的防止表单重复提交的功能把!
这里写图片描述在需要提交的表单上使用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>
这里写图片描述
测试
这里写图片描述如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章,想要获取更多的Java资源的同学,可以关注微信公众号:Java3y