博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
解决SpringMVC重复提交的问题
阅读量:4316 次
发布时间:2019-06-06

本文共 5840 字,大约阅读时间需要 19 分钟。

方法一:通过重定向

采取请求转发的方式完成表单内容的添加会造成内容的重复插入。
当向Servlet发送一条增加记录的请求后,servlet首先向数据库增加一条记录,然后又从数据库中查询出所有数据,接着转发到另一个页面,这时,页面上浏览器的地址显示的是servlet的地址,当用户刷新页面时,又会向servlet发送一条添加请求,这样会导致数据库中重复数据不断增加。
解决办法:采用重定向的方式添加数据不会导致数据的重复插入或删除。
向servlet发送一个添加请求时,这个servlet只执行添加操作,然后重定向到另一个servlet进行数据的查询,最后转发到显示页面。
方法二:重点推荐--利用Session Token的方式

在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。

在下列情况下,服务器程序将拒绝处理用户提交的表单请求:

1.存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。

2.当前用户的Session中不存在Token(令牌)。

3. 用户提交的表单数据中没有Token(令牌)。

具体实现如下:

步骤一:创建FormServlet,用于生成Token(令牌)和跳转到form.jsp页面

1 package item.google.session;   2    3 import java.io.IOException;   4 import javax.servlet.ServletException;   5 import javax.servlet.http.HttpServlet;   6 import javax.servlet.http.HttpServletRequest;   7 import javax.servlet.http.HttpServletResponse;   8    9 public class FormServlet extends HttpServlet {  10     private static final long serialVersionUID = -884689940866074733L;  11   12     public void doGet(HttpServletRequest request, HttpServletResponse response)  13             throws ServletException, IOException {  14   15         String token = TokenProccessor.getInstance().makeToken();//创建令牌  16         System.out.println("在FormServlet中生成的token:"+token);  17         request.getSession().setAttribute("token", token);  //在服务器使用session保存token(令牌)  18         request.getRequestDispatcher("/form.jsp").forward(request, response);//跳转到form.jsp页面  19     }  20   21     public void doPost(HttpServletRequest request, HttpServletResponse response)  22             throws ServletException, IOException {  23         doGet(request, response);  24     }  25   26 }
View Code

步骤二:生成Token的工具类TokenProccessor

1 package item.google.session;   2    3 import java.security.MessageDigest;   4 import java.security.NoSuchAlgorithmException;   5 import java.util.Random;   6 import sun.misc.BASE64Encoder;   7    8 public class TokenProccessor {   9   10     /* 11      *单例设计模式(保证类的对象在内存中只有一个) 12      *1、把类的构造函数私有 13      *2、自己创建一个类的对象 14      *3、对外提供一个公共的方法,返回类的对象 15      */  16     private TokenProccessor(){}  17       18     private static final TokenProccessor instance = new TokenProccessor();  19       20     /** 21      * 返回类的对象 22      * @return 23      */  24     public static TokenProccessor getInstance(){  25         return instance;  26     }  27       28     /** 29      * 生成Token 30      * Token:Nv6RRuGEVvmGjB+jimI/gw== 31      * @return 32      */  33     public String makeToken(){  //checkException  34         //  7346734837483  834u938493493849384  43434384  35         String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";  36         //数据指纹   128位长   16个字节  md5  37         try {  38             MessageDigest md = MessageDigest.getInstance("md5");  39             byte md5[] =  md.digest(token.getBytes());  40             //base64编码--任意二进制编码明文字符   adfsdfsdfsf  41             BASE64Encoder encoder = new BASE64Encoder();  42             return encoder.encode(md5);  43         } catch (NoSuchAlgorithmException e) {  44             throw new RuntimeException(e);  45         }  46     }  47 }
View Code

步骤三:DoFormServlet处理表单提交

1 package item.google.session;   2    3 import java.io.IOException;   4 import javax.servlet.ServletException;   5 import javax.servlet.http.HttpServlet;   6 import javax.servlet.http.HttpServletRequest;   7 import javax.servlet.http.HttpServletResponse;   8    9 public class DoFormServlet extends HttpServlet {  10   11     public void doGet(HttpServletRequest request, HttpServletResponse response)  12                 throws ServletException, IOException {  13   14             boolean b = isRepeatSubmit(request);//判断用户是否是重复提交  15             if(b==true){  16                 System.out.println("请不要重复提交");  17                 return;  18             }  19             request.getSession().removeAttribute("token");//移除session中的token  20             System.out.println("处理用户提交请求!!");  21         }  22           23         /** 24          * 判断客户端提交上来的令牌和服务器端生成的令牌是否一致 25          * @param request 26          * @return  27          *         true 用户重复提交了表单  28          *         false 用户没有重复提交表单 29          */  30         private boolean isRepeatSubmit(HttpServletRequest request) {  31             String client_token = request.getParameter("token");  32             //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单  33             if(client_token==null){  34                 return true;  35             }  36             //取出存储在Session中的token  37             String server_token = (String) request.getSession().getAttribute("token");  38             //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单  39             if(server_token==null){  40                 return true;  41             }  42             //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单  43             if(!client_token.equals(server_token)){  44                 return true;  45             }  46               47             return false;  48         }  49   50     public void doPost(HttpServletRequest request, HttpServletResponse response)  51             throws ServletException, IOException {  52         doGet(request, response);  53     }  54   55 }
View Code

步骤四:在form.jsp中使用隐藏域来存储Token(令牌)

1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>   2    3    4    5 form表单   6    7    8    9     
10 <%--使用隐藏域存储生成的token--%> 11 <%-- 12
"> 13 --%> 14 <%--使用EL表达式取出存储在session中的token--%> 15
16 用户名:
17
18
19 20
View Code

 

 

 

转载于:https://www.cnblogs.com/timePasser-leoli/p/7543299.html

你可能感兴趣的文章
MapReduce的倒排索引
查看>>
Heterogeneity Activity Recognition Data Set类别
查看>>
服务中的 API 网关(API Gateway)
查看>>
Android--TextView第一个单词大写
查看>>
网友给的链接
查看>>
《2017011.17-构建之法:现代软件工程-阅读笔记3》
查看>>
sourceinsight4
查看>>
C#实现四部电梯的调度
查看>>
Android SDK版本和ADT版本
查看>>
TCL的艰难生存之路
查看>>
Flask最强攻略 - 跟DragonFire学Flask - 第五篇 做一个用户登录之后查看学员信息的小例子...
查看>>
Android笔记(四十) Android中的数据存储——SQLite(二) insert
查看>>
newcoder【NOIP2018普及组模拟赛第一次】C题
查看>>
关于PC端页面适应不了手机端的问题 解决方案
查看>>
多线程 基本概念
查看>>
电报压缩/解压缩系统
查看>>
[UE4]C++ getter and setter
查看>>
[UE4]机器人射击逻辑行为树
查看>>
CentOS系统将UTC时间修改为CST时间
查看>>
Django学习笔记8
查看>>