浅谈利用Session防止表单重复提交
作者:amork 发布时间:2022-02-08 00:45:42
解决项目中表单重复提交的问题,在平常的项目中有以下几种可能出现表单重复提交的情况,比如说:
1.由于服务器缓慢或者网络延迟的原因,重复点击提交按钮
2.已经提交成功,但是还不停刷新成功页面
3.已经提交成功,通过回退,再次点击提交按钮。
这些情况都可能使数据库中产生过多相同的冗余数据,浪费数据库资源。只有转发才会出现,重定向则不会。
针对第一种情况的解决方案(使用JavaScript),对后面两种无效:
首先在页面中添加如下格式的JavaScript代码
var submitFlag=false;
function checksubmit(){
if(!submitFlag){
submitFlag=true;
document.forms[0].submit();
}
}
(1)当提交按钮的type属性为button时:
设置按钮的onClick=”checksubmit();”即可。
(2)当提交按钮的type属性为submit时:
设置按钮的onClick=”checksubmit();”,并在<form>标签中增加onsubmit=”returnfalse”。因为submit按钮的自动提交时在点击事件提交之后,将onsubmit设置为”returnfalse”,submit按钮的自动提交就会失效。
对于后面两种情况,可以使用session解决,其原理是在运行添加信息页面时在session中放置信息,然后页面提交信息给servlet处理,servlet获取session中的信息,如果session中有信息不为空则将信息插入数据库,然后删除session中的信息,下次再提交表单时session中的信息为空,那么则不执行存储信息过程。
但是单纯使用session有其局限性,所以在实际开发中,一般使用利用session结合UUID解决表单的重复提交,代码如下:
定义一个UuidToken类
public class UuidToken {
private static UuidToken UuidToken=new UuidToken();
private UuidToken(){
}
public static UuidToken getUuidToken() {
return UuidToken;
}
public synchronized String getUUIDAsStr(HttpServletRequest request){
HttpSession session=request.getSession();
String uuidStr=UUID.randomUUID().toString();
if(uuidStr!=null){
session.setAttribute("session.uuid", uuidStr);
}
return uuidStr;
}
/**
* 判断session中保存的uuid和jsp页面上的uuid是否相等
*/
public synchronized Boolean isUUIDValidate(HttpServletRequest request) {
//获取已存在的session
HttpSession session=request.getSession(false);
if(session==null){
return false;
}
String sessionuuid = (String)session.getAttribute ("session.uuid");
if(sessionuuid==null){
return false;
}
String htmluuid=request.getParameter("html.uuid");
if(htmluuid==null){
return false;
}
return sessionuuid.equals(htmluuid);
}
/**
* 删除uuid
*/
public synchronized void resetUUID(HttpServletRequest request) {
HttpSession session=request.getSession(false);
if(session==null){
return;
}
session.removeAttribute("session.uuid");
}
}
在jsp页面增加一个隐藏域,利用uuid生成一个唯一的标识号,赋给隐藏域,把唯一的标识号 放置到session中一份,代码如下:
<input type="hidden" name="html.uuid" value='<%=UuidToken.getUuidToken().getUUIDAsStr(request)%>'>
提交给servlet后,获取 jsp页隐藏域的值,用隐藏域的值和session中放置的值做比对,如果相同,保存数据并从session中删除UUID,不相同则说明是重复提交,不进行处理。
Boolean flag= UuidToken.getUuidToken().isUUIDValidate(request);
if(flag){
// 保存信息到数据库
//从session删除uuid的
UuidToken.getUuidToken().resetUUID(request);
} else{
System.out.println("表单重复提交");
}
来源:http://blog.csdn.net/amork/article/details/6247168
猜你喜欢
- 最初,XML 语言仅仅是意图用来作为 HTML 语言的替代品而出现的,但是随着该语言的不断发展和完善,人们越来越发现它所具有的优点:例如标记
- 在C程序代码中我们可以利用操作系统提供的互斥锁来实现同步块的互斥访问及线程的阻塞及唤醒等工作。然而在Java中除了提供LockAPI外还在语
- 对象是对类的实例化。对象具有状态和行为,变量用来表明对象的状态,方法表明对象所具有的行为。Java 对象的生命周期包括创建、使用和清除。一、
- Spring Cache设置缓存条件原理从Spring3.1开始,Spring框架提供了对Cache的支持,提供了一个对缓存使用的抽象,通过
- 前言SpringBoot是我们经常使用的框架,那么你能不能针对SpringBoot实现自动配置做一个详细的介绍。如果可以的话,能不能画一下实
- 1、包装类型是什么?Java 为每一个基本数据类型都引入了对应的包装类型,int 的包装类就是 Integer,从 Java 5 开始引入了
- web 容器的设计开发一个web容器涉及很多不同方面不同层面的技术,例如通信层的知识,程序语言层面的知识等等,且一个可用的web容器是一个比
- 前言数据库访问是web应用必不可少的部分。现今最常用的数据库ORM框架有Hibernate与Mybatis,Hibernate貌似在传统IT
- 接收JSON浏览器传来的参数,可以是 key/value 形式的,也可以是一个 JSON 字符串。在 Jsp/Servlet 中,我们接收
- 前言本文主要给大家介绍了关于Android如何实现移动小球和CircularReveal页面切换动画的相关内容,分享出来供大家参考学习,下面
- 废话少说,直接上代码:ehcache.xml 文件<?xml version="1.0" encoding=&qu
- 在Android中因为不同像素手机的多样化,对于一张图片,放大不同的手机上因像素不同显示上也会有区别。现有如下需求:将一张图片宽度充满整个屏
- 一、JMeter后端 * 介绍说到JMeter后端 * ,必须要从源头BackendListener开始说,最后延伸到我们需要的Backen
- 1.map遍历快速实现边距,文字自适应改变大小Container( // padding: EdgeI
- 一.Worker Thread模式Worker的意思是工作的人,在Worker Thread模式中,工人线程Worker thread会逐个
- 本文实例讲述了Java定义泛型方法。分享给大家供大家参考,具体如下:一 点睛1 如果定义类、接口是没有使用类型形参,但定义方法时想自己定义类
- 前一篇博文介绍了JDK logging基础知识 博文中也提到LogManager,本章主要阐述怎么完全定制化LogManager来
- 本文主要介绍了关于c#和java base64不一致的解决方法,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧不一致的问题不
- Android指定SnackBar在屏幕的位置Snackbar 常以一个小的弹出框的形式,出现在手机屏幕下方或者桌面左下方,并且是在屏幕所有
- 一、场景描述建造者模式同工厂模式、抽象工厂模式一样,用于创建继承类对象。工厂模式:Java设计模式之工厂模式抽象工厂模式:Java设计模式之