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页面把
测试
Struts2第十三篇【防止表单重复提交】的更多相关文章
- Struts2笔记——利用token防止表单重复提交
在一些项目中经常会让用户提交表单,当用户点击按钮提交后,如果再次浏览器刷新,这就会造成表单重复提交,若是提交的内容上传至服务器并请求数据库保存,重复提交的表单可能会导致错误,然后跳转到错误界面,这是一 ...
- spring boot 学习(七)小工具篇:表单重复提交
注解 + 拦截器:解决表单重复提交 前言 学习 Spring Boot 中,我想将我在项目中添加几个我在 SpringMVC 框架中常用的工具类(主要都是涉及到 Spring AOP 部分知识).比如 ...
- struts2 模拟令牌机制防止表单重复提交
web.xml: <?xml version="1.0" encoding="UTF-8"?><web-app version="3 ...
- 12、Struts2表单重复提交
什么是表单重复提交 表单的重复提交: 若刷新表单页面, 再提交表单不算重复提交. 在不刷新表单页面的前提下: 多次点击提交按钮 已经提交成功, 按 "回退" 之后, 再点击 &qu ...
- Struts2防止表单重复提交
1.说明 系统拦截器的应用. 表单重复提交:当使用请求转化进行跳转的时候,存在着表单重复提交的问题. 2.在表单中加入s:token 如果页面加入了struts2的标签,页面的请求必须进入struts ...
- 【转】Struts2解决表单重复提交问题
用户重复提交表单在某些场合将会造成非常严重的后果.例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次.因此,重复提 ...
- [原创]java WEB学习笔记73:Struts2 学习之路-- strut2中防止表单重复提交
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- struts2视频学习笔记 29-30(Struts 2常用标签,防止表单重复提交)
课时28 Struts 2常用标签解说 property标签 property标签用于输出指定值: <s:set name="name" value="'kk'&q ...
- struts2之防止表单重复提交
struts.xml配置文件 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts ...
随机推荐
- 读懂javascript深拷贝与浅拷贝
1. 认识深拷贝和浅拷贝 javascript中一般有按值传递和按引用传递两种复制,按值传递的是基本数据类型(Number,String,Boolean,Null,Undefined),一般存放于内存 ...
- Vue-上拉加载与下拉刷新(mint-ui:loadmore)一个页面使用多个上拉加载后冲突问题
所遇问题: 该页面为双选项卡联动,四个部分都需要上拉加载和下拉刷新功能,使用的mint-ui的loadmore插件,分别加上上拉加载后,只有最后一个的this.$refs.loadmore.onTop ...
- jquery的2.0.3版本源码系列(6):2880-3042行,回调对象,对函数的统一管理
目录 1 . 回调对象callbacks的演示 回调的使用有一点像事件绑定,先绑定好,等到有点击事件或者其他时就触发. <script src="js/jquery-2.0.3.js& ...
- 我的前端故事----关于redux的一些思考
背景 我一个前端,今年第一份工作就是接手一个 APP 的开发...一个线下 BD 人员用的推广 APP,为了让我这个一天原生开发都没有学过的人能快速开发上线,于是乎就选择了 react-native ...
- Scala中柯里化函数
高阶函数转一阶函数: val add1 = (x: Int) => x + 5 def add2(x: Int)(y: Int) = x + y //传入一个参数转换为一阶函数 def add3 ...
- iOS 环信集成单聊界面,出现消息重复问题
解决办法很简单,数据重复就是EaseMessageViewController和ChatViewController重复调用了这个吧?//通过会话管理者获取收发消息 [self tableViewDi ...
- makefile初步制作,arm-linux- (gcc/ld/objcopy/objdump)详解
在linux中输入vi Makefile 来实现创建Makefile文件 注意:命令行前必须加TAB键 例如:将两个文件led.c和crt0.S汇编文件,制作一个Makefile文件 led.bin ...
- poj 1986LCA离线dfs+并查集
题意,给出边和权值,求出两个点间的最短距离. 用离线算法的时候有个地方不知道怎么处理了.在线的本来想用倍增的,但发现倍增算法貌似需要预处理深度而不是权值,不知道怎么处理.套一个rmq的模板吧,用来处理 ...
- js实现换肤效果
一,js换肤的基本原理 基本原理很简单,就是使用 JS 切换对应的 CSS 样式表文件.例如导航网站 Hao123 的右上方就有网页换肤功能.除了切换 CSS 样式表文件之外,通常的网页换肤还需要通过 ...
- 所谓编码--泛谈ASCII、Unicode、UTF8、UTF16、UCS-2等编码格式
最近在看nodejs的源码,看到stream的实现里面满地都是encoding,不由想起以前看过的一篇文章--在前面的随笔里面有提到过--阮一峰老师的<字符编码笔记:ASCII,Unicode和 ...