JavaWeb中HttpSession中表单的重复提交示例
发布时间 - 2026-01-10 23:21:35 点击率:次表单的重复提交

- 重复提交的情况:
①. 在表单提交到一个 Servlet,而 Servlet 又通过请求转发的方式响应了一个 JSP(HTML)页面,此时地址栏还保留着 Servlet 的那个路径,在响应页面点击 “刷新”。
②. 在响应页面没有到达时,重复点击 “提交按钮”
③. 点击返回,再点击提交
- 不是重复提交的情况:点击 “返回”,“刷新” 原表单页面,再点击提交。
- 如何避免表单的重复提交:在表单中做一个标记,提交到 Servlet 时,检查标记是否存在且和预定义的标记一样,若一致,则受理请求,并销毁标记,若不一致或没有标记,则直接响应提示信息:“重复提交”
①仅提供一个隐藏域不行:<input type="hidden" name="token" value="lsy">
②把标记放在 Request 中 , 行不通,表单页面刷新后,request 已经被销毁,再提交表单是一个新的 request 的。
③把标记放在 Session 中,可以
1. 在原表单页面,生成一个随机值 token
2. 在原表单页面,把 token 值放入 session 属性中
3. 在原表单页面,把 token 值放入到隐藏域
4. 在目标的 Servlet 中:获取 session 和隐藏域中的 token 值
比较两个值是否一致,受理请求,且把 session 域中的 token 属性清除,若不一致,则直接响应提示页面:“重复提交”
我们可以通过 Struts1 中写好的类 TokenProcessor 来重构代码, 面向组件编程
package com.lsy.javaweb;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class TokenProcessor {
private static final String TOKEN_KEY = "TOKEN_KEY";
private static final String TRANSACTION_TOKEN_KEY = "TRANSACTION_TOKEN_KEY";
/**
* The singleton instance of this class.
*/
private static TokenProcessor instance = new TokenProcessor();
/**
* The timestamp used most recently to generate a token value.
*/
private long previous;
/**
* Protected constructor for TokenProcessor. Use
* TokenProcessor.getInstance() to obtain a reference to the processor.
*/
protected TokenProcessor() {
super();
}
/**
* Retrieves the singleton instance of this class.
*/
public static TokenProcessor getInstance() {
return instance;
}
/**
* <p>
* Return <code>true</code> if there is a transaction token stored in the
* user's current session, and the value submitted as a request parameter
* with this action matches it. Returns <code>false</code> under any of the
* following circumstances:
* </p>
*
* <ul>
*
* <li>No session associated with this request</li>
*
* <li>No transaction token saved in the session</li>
*
* <li>No transaction token included as a request parameter</li>
*
* <li>The included transaction token value does not match the transaction
* token in the user's session</li>
*
* </ul>
*
* @param request
* The servlet request we are processing
*/
public synchronized boolean isTokenValid(HttpServletRequest request) {
return this.isTokenValid(request, false);
}
/**
* Return <code>true</code> if there is a transaction token stored in the
* user's current session, and the value submitted as a request parameter
* with this action matches it. Returns <code>false</code>
*
* <ul>
*
* <li>No session associated with this request</li>
* <li>No transaction token saved in the session</li>
*
* <li>No transaction token included as a request parameter</li>
*
* <li>The included transaction token value does not match the transaction
* token in the user's session</li>
*
* </ul>
*
* @param request
* The servlet request we are processing
* @param reset
* Should we reset the token after checking it?
*/
public synchronized boolean isTokenValid(HttpServletRequest request, boolean reset) {
// Retrieve the current session for this request
HttpSession session = request.getSession(false);
if (session == null) {
return false;
}
// Retrieve the transaction token from this session, and
// reset it if requested
String saved = (String) session.getAttribute(TRANSACTION_TOKEN_KEY);
if (saved == null) {
return false;
}
if (reset) {
this.resetToken(request);
}
// Retrieve the transaction token included in this request
String token = request.getParameter(TOKEN_KEY);
if (token == null) {
return false;
}
return saved.equals(token);
}
/**
* Reset the saved transaction token in the user's session. This indicates
* that transactional token checking will not be needed on the next request
* that is submitted.
*
* @param request
* The servlet request we are processing
*/
public synchronized void resetToken(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(TRANSACTION_TOKEN_KEY);
}
/**
* Save a new transaction token in the user's current session, creating a
* new session if necessary.
*
* @param request
* The servlet request we are processing
*/
public synchronized String saveToken(HttpServletRequest request) {
HttpSession session = request.getSession();
String token = generateToken(request);
if (token != null) {
session.setAttribute(TRANSACTION_TOKEN_KEY, token);
}
return token;
}
/**
* Generate a new transaction token, to be used for enforcing a single
* request for a particular transaction.
*
* @param request
* The request we are processing
*/
public synchronized String generateToken(HttpServletRequest request) {
HttpSession session = request.getSession();
return generateToken(session.getId());
}
/**
* Generate a new transaction token, to be used for enforcing a single
* request for a particular transaction.
*
* @param id
* a unique Identifier for the session or other context in which
* this token is to be used.
*/
public synchronized String generateToken(String id) {
try {
long current = System.currentTimeMillis();
if (current == previous) {
current++;
}
previous = current;
byte[] now = new Long(current).toString().getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(id.getBytes());
md.update(now);
return toHex(md.digest());
} catch (NoSuchAlgorithmException e) {
return null;
}
}
/**
* Convert a byte array to a String of hexadecimal digits and return it.
*
* @param buffer
* The byte array to be converted
*/
private String toHex(byte[] buffer) {
StringBuffer sb = new StringBuffer(buffer.length * 2);
for (int i = 0; i < buffer.length; i++) {
sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
}
return sb.toString();
}
}
以上所述是小编给大家介绍的JavaWeb中HttpSession中表单的重复提交示例,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
# javaweb
# httpsession表单
# 表单重复提交
# 浅谈利用Session防止表单重复提交
# 表单
# 放在
# 若不
# 小编
# 再点
# 是一个
# 在此
# 提示信息
# 我们可以
# 给大家
# 提供一个
# 所述
# 给我留言
# 写好
# 感谢大家
# 是否存在
# 再提
# 中做
# 重构
# 疑问请
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel表单请求验证类怎么用_Laravel Form Request分离验证逻辑教程
昵图网官网入口 昵图网素材平台官方入口
Windows10怎样连接蓝牙设备_Windows10蓝牙连接步骤【教程】
动图在线制作网站有哪些,滑动动图图集怎么做?
简单实现Android文件上传
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
齐河建站公司:营销型网站建设与SEO优化双核驱动策略
android nfc常用标签读取总结
C#如何调用原生C++ COM对象详解
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
历史网站制作软件,华为如何找回被删除的网站?
如何快速辨别茅台真假?关键步骤解析
如何在阿里云高效完成企业建站全流程?
详解jQuery中基本的动画方法
Laravel如何操作JSON类型的数据库字段?(Eloquent示例)
如何用美橙互联一键搭建多站合一网站?
Laravel如何实现用户注册和登录?(Auth脚手架指南)
laravel怎么使用数据库工厂(Factory)生成带有关联模型的数据_laravel Factory生成关联数据方法
如何在自有机房高效搭建专业网站?
UC浏览器如何设置启动页 UC浏览器启动页设置方法
网站优化排名时,需要考虑哪些问题呢?
Laravel如何生成和使用数据填充?(Seeder和Factory示例)
HTML 中动态设置元素 name 属性的正确语法详解
打造顶配客厅影院,这份100寸电视推荐名单请查收
🚀拖拽式CMS建站能否实现高效与个性化并存?
详解vue.js组件化开发实践
Laravel怎么导出Excel文件_Laravel Excel插件使用教程
如何快速查询网站的真实建站时间?
如何快速搭建高效简练网站?
,交易猫的商品怎么发布到网站上去?
Laravel如何处理JSON字段_Eloquent原生JSON字段类型操作教程
如何在企业微信快速生成手机电脑官网?
米侠浏览器网页图片不显示怎么办 米侠图片加载修复
Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】
香港服务器租用费用高吗?如何避免常见误区?
Laravel怎么生成URL_Laravel路由命名与URL生成函数详解
夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化
jQuery中的100个技巧汇总
Laravel如何为API编写文档_Laravel API文档生成与维护方法
javascript如何操作浏览器历史记录_怎样实现无刷新导航
Windows驱动无法加载错误解决方法_驱动签名验证失败处理步骤
Laravel怎么判断请求类型_Laravel Request isMethod用法
EditPlus中的正则表达式实战(5)
html如何与html链接_实现多个HTML页面互相链接【互相】
米侠浏览器网页背景异常怎么办 米侠显示修复
百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏
如何用好域名打造高点击率的自主建站?
武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?
深圳网站制作设计招聘,关于服装设计的流行趋势,哪里的资料比较全面?
如何在建站之星绑定自定义域名?

