解决表单重复提交的解决方案——在服务端对Token进行验证
1、在idea中建立一个springboot项目
2、在templates目录下建立一个index.html文件
<!DOCTYPE html>
<html lang="en" xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context">
<head>
<mvc:annotation-driven enable-matrix-variables="true"/>
<context:component-scan base-package="com.example.demo"/>
<mvc:default-servlet-handler/>
<meta charset="utf-8" />
<title>首页</title>
</head>
<body>
<p>
<a href="/h2">链接</a> //点击链接,来到表单提交页面
</p>
</body>
</html>
3、在templates目录下建立index3.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="/b/js/jquery-3.4.1.min.js"></script>
<script>
function f2() {
$.ajax({
url:"/get_token", //向服务器端发送的请求地址
success:function (data) {
console.log(data);
$("#h").val(data) //把返回的token放入input中,随表单提交给后端
}
})
}
</script>
</head>
<body>
<form action="/h3" id="dd" method="post">
用户名:<input type="text" id="u" name="user_name">
密码:<input type="text" id="p" name="psd" onblur="f2()"> //当鼠标离开密码输入框时,触发f()函数,向后端发送一个ajax请求
<input type="submit" value="提交" >
<input type="hidden" id="h" name="token"> //通过ajax请求,把服务端生成的token放入该input中
</form>
</body>
</html>
4、建立一个Controller
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.UUID;
@Controller
public class Token_controller {
@ResponseBody
@RequestMapping("/get_token") //利用ajax请求,给前端返回一个token
public String get1(HttpServletRequest httpServletRequest) {
UUID uuid = UUID.randomUUID(); //利用UUID获得一个token,返回给前端的表单中
String str = uuid.toString();
HttpSession session = httpServletRequest.getSession();
session.setAttribute("token", str);
return str;
}
@RequestMapping("/h2")
public String get2() {
return "index3";
}
@RequestMapping("/h3")
public String get3(String token, HttpServletRequest httpServletRequest) throws InterruptedException {
Thread.sleep(3000); //让线程等待3秒,模拟网络拥挤的情况
HttpSession session = httpServletRequest.getSession();
String tokens = (String) session.getAttribute("token");
if (tokens == null || tokens.equals("") || (!(tokens.equals(token)))) //判断从session中是否有token,若无则表单重复提交,若session
{ //中的token值与前端表单中传过来的值不相同,也提示表单重复提交
System.out.println("提交失败!");
} else { //表单提交成功
System.out.println("提交成功!");
session.removeAttribute("token");
return "index";
}
return "index"; //返回首页
}
}
5、运行项目
点击多次提交按钮,只有一个请求被接收,从根本上解决了表单重复提交的问题!
6、总结
1、在导入jQuery时要注意路径问题,若出现无法加载jQuery的问题,首先检查jQuery所在的静态资源路径是否被拦截,在springboot2.0以后,会默认拦截静态资源,需要添加一个WebMvcConfigurer来添加静态资源的目录。如果不是这个问题,再检查jQuery的请求路径是否正确,一般都是出现这个问题。
2、在后端对tokens进行判断是应该用(tokens == null || tokens.equals("")),不然会报空指针异常。
3、在服务器端解决是根本的方法,常用的其他几种方法,例如在前端进行判断有他的局限性,若用户点击后退,表单还是会进行再次提交。