1. 程式人生 > 其它 >攔截器-防重複提交

攔截器-防重複提交

為了保證介面冪等性,需要前後端都要做處理。

1 前端-提交按鈕置灰,不再請求介面。

2 後盾-防重複提交。

package com.jiutong.zqp.manage.interceptor;

import groovy.util.logging.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
import java.util.Objects; import java.util.concurrent.TimeUnit; /** * bi 防重複提交 * @author zhouq */ @Slf4j public class RedisResubmitInterceptor implements HandlerInterceptor { private static final String RESUBMIT_TOKEN; static { RESUBMIT_TOKEN = "bi_resubmit_token_"; } protected
Logger logger = LoggerFactory.getLogger(getClass()); @Autowired private RedisTemplate redisTemplate; private String[] NOT_INTERCEPT_URL = {"newOrders/orderStatusCount", "newOrders/getBuyerOrders","/views","/resources"}; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object shrioUser = null; try { //獲取登入使用者ID shrioUser = SecurityUtils.getSubject().getSession().getAttribute("adminUid"); } catch (Exception e) { } if (shrioUser == null) { return true; } Integer userId = (Integer)shrioUser; if (userId == null || Objects.equals(userId, 0)) { return true; } //獲取請求路徑 String methodFullName = request.getRequestURI() + "_" + userId; //其他請求不做防重複提交 for (String url: NOT_INTERCEPT_URL) { if (StringUtils.indexOf(methodFullName, url) > 0) { return true; } } //路徑加密 String resubmitTokenKey = RESUBMIT_TOKEN + MD5.MD5Encode(methodFullName); logger.debug("resubmitTokenKey lock key: " + resubmitTokenKey); //redis模版k-v 鍵值操作 ValueOperations<String, String> valueOps = redisTemplate.opsForValue(); //redis 如果resubmitTokenKey相同,自增 long count = valueOps.increment(resubmitTokenKey, 1); // 如果等於1,說明是第一個請求,如果該KEY的數值大於1,說明是第一次請求處理未完成,重複提交的請求,不做處理 if (count == 1) { // 設定有效期 redisTemplate.expire(resubmitTokenKey, 30, TimeUnit.SECONDS); logger.debug("resubmitTokenKey get lock, key: " + resubmitTokenKey + " , expire in 20 seconds."); return true; } else { //判斷日誌級別 if (logger.isDebugEnabled()) { String desc = String.valueOf(valueOps.get(resubmitTokenKey)); logger.debug("resubmitTokenKey key: " + resubmitTokenKey + " locked by another business:" + desc); } return false; } } @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { Object shrioUser = null; try { shrioUser = SecurityUtils.getSubject().getSession().getAttribute("adminUid"); } catch (Exception e) { } if (shrioUser == null) { return ; } Integer userId = (Integer)shrioUser; String methodFullName = request.getRequestURI() + "_" + userId; String resubmitTokenKey = RESUBMIT_TOKEN + MD5.MD5Encode(methodFullName); //響應成功,刪除快取 redisTemplate.delete(resubmitTokenKey); } }