博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
阿里P7告诉你SpringBoot如何防止重复提交?
阅读量:6472 次
发布时间:2019-06-23

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

有两种防止重复提交:

  1. 禁用提交按钮
  2. 发出请求令牌/ ID:

禁用提交按钮

我们可以在函数调用HTTP请求之前禁用提交按钮,并在完成HTTP响应后再次启用它。该技术对于需要很长时间才能完成的过程(超过5秒)是有效的。由于不耐烦而无法获得结果,用户无法再次单击n'。此外,我们可能会显示一个正在Loading装载进度,以获得良好的体验。

            
...

在beforeSend 和complete段,我添加“ disable”属性作为开关, (jquery中有专门语句防止二次提交)

重点来了:

Spring Boot中如何发出请求令牌/ ID

这种技术实际上更复杂,更难实现,但是由于一个好的框架(如Spring Boot)使这更容易。在我们开始代码实现之前,让我们先讨论一下这个机制;

  • 加载表单页面时,发出新的requestId
  • 在调用后端服务之前将已发出的requestId发送到HTTP头
  • 后端服务标识requestId是否已注册
  • 如果requestId已经注册,那么我们可以将其标记为违规请求

我们来开始代码。这里是我的JavaScript中的示例代码,用于发出新的requestId。

$(document).ready(function () {        var requestId = new Date().getTime(); // <--- issue new requestId every time page laoded                $('#form-payment').submit(function (e) {            e.preventDefault();            $.ajax({                type: 'POST',                dataType : "json",                contentType: "application/json; charset=utf-8",                headers: { "requestId" : requestId }, // <--- add requestId in header                url: "#",                data: "{}",                beforeSend: function(){                    $('#button-submit').attr('disabled', 'disable');                },                complete: function(){                    $('#button-submit').removeAttr('disabled');                },                success: function (data) {                                },                error: function () {                                }            });        });    });

这里是我的Spring Boot项目中的示例代码,我创建了一个Interceptor来处理requestId:

import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.util.ArrayList;import java.util.List;@Configurationpublic class Interceptor implements WebMvcConfigurer {    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(new ViolationInterceptor()).addPathPatterns("/**");    }    public class ViolationInterceptor extends HandlerInterceptorAdapter {        private List
requestIds = new ArrayList<>(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestId = request.getHeader("requestId"); if (requestIds.contains(requestId)) throw new IllegalArgumentException("Violation Request; Reason requestId already registered"); requestIds.add(requestId); return super.preHandle(request, response, handler); } }}

Exception处理:

import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;@ControllerAdvicepublic class ExceptionAdvisor {    @ExceptionHandler(IllegalArgumentException.class)    ResponseEntity illegalArgumentExceptionHandler(IllegalArgumentException e){        return ResponseEntity.ok(e.getMessage());    }}

在此示例中,我使用应用程序内存来​​存储requestId。对于认真的开发,我建议使用内存数据库,例如Redis。

实际上,我们可以在识别requestId时修改如何发布新令牌和逻辑。因为这个过程非常简单,我们需要一些东西(requestId)来识别已经请求过的东西。

写在最后:

既然看到这里了,觉得笔者写的还不错的就点个赞,加个关注呗!点关注,不迷路,持续更新!!!

转载地址:http://movko.baihongyu.com/

你可能感兴趣的文章
算法 (二分查找算法)
查看>>
java Date 当天时间戳处理
查看>>
Python~迭代
查看>>
linux常用命令-关机、重启
查看>>
css布局 - 九宫格布局的方法汇总(更新中...)
查看>>
画图函数——点,线,矩形等等
查看>>
ejabberd_local
查看>>
BZOJ5020 [THUWC 2017]在美妙的数学王国中畅游LCT
查看>>
hdu 6030 矩阵快速幂
查看>>
tomcat类加载机制
查看>>
ado.net2.0中的缓存使用SqlDependency类
查看>>
Java基础学习总结(94)——Java线程再学习
查看>>
iOS开发之调用系统设置
查看>>
利用 ACPI\\ACPI0003设备 判断笔记本还是台式机
查看>>
解决wampserver 服务无法启动
查看>>
ES6中Promise封装ajax的写法
查看>>
初次使用 VUX
查看>>
javascript 字符串转数字的简便写法
查看>>
0404《构建之法》第四章读后感
查看>>
html之div始终停留在屏幕中间部分
查看>>