再発行してください:ユーザーがクリックを提出した後、デーモンプロセスが完了していない、ユーザーが知らない、せっかちなっていた、と常にデータエラーが生じ、操作を繰り返して提出した複数のバックエンドデータにつながる、[送信]をクリックします。それでは、どのようにこの問題を解決するには?
解決する方法は2つあります。
1.フロントコントロール
【0002】セッション裁判官
フロントコントロールは2つの方法があり、一つはボタンがグレーアウトされて提出提出した後による、1はJSコントロールによって一度だけ送信された(非常に良いその経験をお勧めしません)ということです。
私たちは、jsの制御を通じて唯一の方法を提出して見てみましょう:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta content="text/html; charset=utf-8">
<title>Form Page</title>
</head>
<body>
<form action="SubmitServlet" method="post" onsubmit = "return isFirstSumbmit()">
<input type = "text" name = "userName" value=""/>
<input type = "submit" value="提交">
</form>
<script type="text/javascript">
//提交标志 true 为已提交,false为未提交
var subFlag = false;
function isFirstSumbmit(){
if(!subFlag){
subFlag = true;
return true;
} else {
return false;
}
}
</script>
</body>
</html>
このモードの欠点は、私は成功を提出した後、フロントコントロールは、その後、[送信]をクリックし、ステップ(バックグラウンドサーブレットをしていない)に戻り、データがまだ繰り返されます提出するには、ブラウザを指していることです。
のは、道のバックエンドセッションを見てみましょう:
サーバーを入力する場合は、一貫して提出全く重複がないことを示す場合には、トークンとサーバのたびに提出を提出するかどうかを比較的フロントエンドと一致し、隠しフィールドの前に設置されたトークンフォームページを生成します。成功したトークンのブランクのデータサービス側を保存した後。提出されていない場合は、繰り返し(または遠位偽造トークン)を表します。
フォームフォームページ:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta content="text/html; charset=utf-8">
<title>Form Page</title>
</head>
<body>
<form action="SubmitServlet" method="post">
<input type = "hidden" name="token" value="${token}"/>
<input type = "text" name = "userName" value=""/>
<input type = "submit" value="提交">
</form>
</body>
</html>
サーブレットフォームページを入力します。
package com.session;
import java.io.IOException;
import java.util.UUID;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
// 进入到 form.jsp 的servlet
public class ToFormPageServlet extends HttpServlet{
public String getToken() {
return UUID.randomUUID().toString();
}
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 随机生成token
String tokenValue = getToken();
HttpSession session = req.getSession();
// token 放入session中
session.setAttribute("token", tokenValue);
System.out.println("生成token成功,token值为:"+ tokenValue);
req.getRequestDispatcher("form.jsp").forward(req, resp);
}
}
フォーム送信サーブレット:
package com.session;
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SubmitServlet extends HttpServlet{
@Override
public void doPost(HttpServletRequest req, HttpServletResponse resp){
resp.setContentType("text/html;charset=utf-8");
if(!isFirstSubmit(req)) {
try {
resp.getWriter().write("表单重复提交!");
} catch (IOException e) {
e.printStackTrace();
}
return ;
}
try {
Thread.sleep(3000);
if(isFirstSubmit(req)){
System.out.println("数据入库"+req.getParameter("userName"));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
resp.getWriter().write("数据保存成功!");
} catch (IOException e) {
e.printStackTrace();
}
// 清除token
req.getSession().removeAttribute("token");
}
/**
* 判断是否重复提交
* @param req
* @return
*/
public boolean isFirstSubmit(HttpServletRequest req) {
// 获取表单提交的token
String token = req.getParameter("token");
// 去拿session里的token
String servicToken = (String)req.getSession().getAttribute("token");
// servicToken 为空 重复提交
if(servicToken == null) {
return false;
}
// 表单提交的token 与服务端的不一致 (防止伪造token)
if(!servicToken.equals(token)) {
return false;
}
return true;
}
}