以前作安卓或蘋果手機應用開發時,好比發帖子,點發布按鈕後時,咱們每每會作一些操做,好比按鈕變灰,而後增長一個轉圈加載的遮罩,主要是爲了防止用戶快速點擊形成屢次提交數據。java
web開發時也會有相似的問題。增長、修改、刪除這些處理業務的操做也會有形成屢次提交數據的問題。web
若是網速比較慢的狀況下,用戶提交表單後,發現服務器半天都沒有響應,那麼用戶可能會覺得是本身沒有提交表單,就會再點擊提交按鈕重複提交表單。面對這個狀況,若是隻是在jsp頁面,加上js判斷的代碼瀏覽器
var checkSubmitFlg = false;服務器
function check(){session
if (checkSubmitFlg == true){dom
alert("重複提交");jsp
return;編碼
}else{spa
checkSubmitFlg = true; .net
myform.submit();
}
}
JavaScript是能夠解決這個問題的,固然還能夠"用JavaScript控制Form表單只能提交一次"。只是點提交按鈕後讓按鈕變灰相似手機端的作法。可是這種作法針對如下2,3場景確不行。
場景二表單提交後用戶點擊【刷新】按鈕致使表單重複提交 和 場景三用戶提交表單後,點擊瀏覽器的【後退】按鈕回退到表單頁面後進行再次提交,用戶這樣的操做爲了解決重複提交表單的問題,咱們能夠在服務端利用session去解決。
具體的作法:在服務器端生成一個惟一的隨機標識號,專業術語稱爲Token(令牌),同時在當前用戶的Session域中保存這個Token。而後將Token發送到客戶端的Form表單中,在Form表單中使用隱藏域來存儲這個Token,表單提交的時候連同這個Token一塊兒提交到服務器端,而後在服務器端判斷客戶端提交上來的Token與服務器端生成的Token是否一致,若是不一致,那就是重複提交了,此時服務器端就能夠不處理重複提交的表單。若是相同則處理表單提交,處理完後清除當前用戶的Session域中存儲的標識號。
在下列狀況下,服務器程序將拒絕處理用戶提交的表單請求:
封裝了一個類TokenProcessor 代碼以下
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import sun.misc.BASE64Encoder;
/**
* 類說明:令牌 防止刷新或程序打斷點或快速點擊 重複提交
* @author wangbx
* @date 2016年11月2日 下午2:41:34
*/
public class TokenProcessor {
private static final TokenProcessor instance = new TokenProcessor();
private TokenProcessor(){}
public static TokenProcessor getInstance(){
return instance;
}
public String generateToken(){
String token = System.currentTimeMillis()+new Random().nextInt()+"";
try{
MessageDigest md = MessageDigest.getInstance("md5");
byte[] md5 = md.digest(token.getBytes());
//base64編碼
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(md5);
}catch(NoSuchAlgorithmException e){
e.printStackTrace();
throw new RuntimeException(e);
}
}
/**
* 功能描述:判斷session中token是否失效 true:沒有失效
* @author wangbx
* @date 2016年11月2日 下午4:04:23
* @param @param request
* @param @return
* @return boolean
*/
public synchronized boolean isTokenValid(HttpServletRequest request) {
String client_token=request.getParameter("token");
if(client_token==null)
{
return false;
}
String server_token=(String)request.getSession().getAttribute("token");
if(server_token==null)
{
return false;
}
if(!client_token.equals(server_token))
{
return false;
}
return true;
}
/**
* 功能描述:爲請求新建一個token標記,並把字符值存入session中
* @author wangbx
* @date 2016年11月2日 下午4:16:41
* @param @param request
* @return void
*/
public synchronized void saveToken(HttpServletRequest request){
HttpSession session = request.getSession(true);
TokenProcessor tp=TokenProcessor.getInstance();
String token=tp.generateToken();
session.setAttribute("token", token);
}
/**
* 功能描述: 從新設置token,當頁面被請求後,將session中的token屬性去除
* @author wangbx
* @date 2016年11月2日 下午4:20:38
* @param @param request
* @return void
*/
public synchronized void resetToken(HttpServletRequest request){
HttpSession session = request.getSession(false);
if(session != null){
session.removeAttribute("token");
}
}
}
針對開發人員的全部模塊 須要在三處複製下代碼
1、jsp界面的form表單裏 加一個隱藏文本框
2、跳到發佈的界面或修改界面前的方法裏 要添加兩行代
3、在具體提交方法加上下面代碼
OK