赞
踩
若依方案
实现思路:
1.将请求的url作为key,参数和时间作为内容存到Redis中;
2.再次发起请求时,根据url查询缓存信息,比较参数和时间;
3.若同一url请求参数相同且在指定时间内,认为它为重复请求,进行拦截。
- import java.lang.annotation.Documented;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Inherited;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
-
- /**
- * 自定义注解防止表单重复提交
- */
- @Inherited
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface RepeatSubmit {
- /**
- * 间隔时间(ms),小于此时间视为重复提交
- */
- public int interval() default 5000;
-
- /**
- * 提示消息
- */
- public String message() default "不允许重复提交,请稍候再试";
- }
- import java.lang.reflect.Method;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- import com.mcs.repeatsubmit.annotation.RepeatSubmit;
- import com.mcs.repeatsubmit.core.AjaxResult;
- import com.mcs.repeatsubmit.core.ServletUtils;
- import org.springframework.stereotype.Component;
- import org.springframework.web.method.HandlerMethod;
- import org.springframework.web.servlet.HandlerInterceptor;
- import com.alibaba.fastjson2.JSON;
-
- /**
- * 防止重复提交拦截器
- *
- * @author ruoyi
- */
- @Component
- public abstract class RepeatSubmitInterceptor implements HandlerInterceptor {
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- if (handler instanceof HandlerMethod) {
- HandlerMethod handlerMethod = (HandlerMethod) handler;
- Method method = handlerMethod.getMethod();
- RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
- if (annotation != null) {
- if (this.isRepeatSubmit(request, annotation)) {
- AjaxResult ajaxResult = AjaxResult.error(annotation.message());
- ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
- return false;
- }
- }
- }
- return true;
- }
-
- /**
- * 验证是否重复提交由子类实现具体的防重复提交的规则
- *
- * @param request
- * @return
- * @throws Exception
- */
- public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
- }
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.TimeUnit;
- import javax.servlet.http.HttpServletRequest;
-
- import com.mcs.repeatsubmit.annotation.RepeatSubmit;
- import com.mcs.repeatsubmit.core.CacheConstants;
- import com.mcs.repeatsubmit.core.HttpHelper;
- import com.mcs.repeatsubmit.core.RedisCache;
- import com.mcs.repeatsubmit.filter.RepeatedlyRequestWrapper;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.stereotype.Component;
- import com.alibaba.fastjson2.JSON;
-
- /**
- * 判断请求url和数据是否和上一次相同,
- * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
- */
- @Component
- public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
- public final String REPEAT_PARAMS = "repeatParams";
-
- public final String REPEAT_TIME = "repeatTime";
-
- // 令牌自定义标识
- @Value("${token.header}")
- private String header;
-
- @Autowired
- private RedisCache redisCache;
-
- @SuppressWarnings("unchecked")
- @Override
- public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) {
- String nowParams = "";
- if (request instanceof RepeatedlyRequestWrapper) {
- RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
- nowParams = HttpHelper.getBodyString(repeatedlyRequest);
- }
- // body参数为空,获取Parameter的数据
- if (StringUtils.isEmpty(nowParams)) {
- nowParams = JSON.toJSONString(request.getParameterMap());
- }
-
- Map<String, Object> nowDataMap = new HashMap<String, Object>();
- nowDataMap.put(REPEAT_PARAMS, nowParams);
- nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
-
- // 请求地址(作为存放cache的key值)
- String url = request.getRequestURI();
-
- // 唯一值(没有消息头则使用请求地址)
- String submitKey = StringUtils.trimToEmpty(request.getHeader(header));
-
- // 唯一标识(指定key + url + 消息头)
- String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
-
- Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
- if (sessionObj != null) {
- Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
- System.out.println(sessionMap);
- if (sessionMap.containsKey(url)) {
- Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
- if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap,
- annotation.interval())) {
- return true;
- }
- }
- }
- Map<String, Object> cacheMap = new HashMap<String, Object>();
- cacheMap.put(url, nowDataMap);
- redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS);
- return false;
- }
-
- /**
- * 判断参数是否相同
- */
- private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) {
- String nowParams = (String) nowMap.get(REPEAT_PARAMS);
- String preParams = (String) preMap.get(REPEAT_PARAMS);
- return nowParams.equals(preParams);
- }
-
- /**
- * 判断两次间隔时间
- */
- private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval) {
- long time1 = (Long) nowMap.get(REPEAT_TIME);
- long time2 = (Long) preMap.get(REPEAT_TIME);
- if ((time1 - time2) < interval) {
- return true;
- }
- return false;
- }
- }
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
- @Configuration
- public class ResourcesConfig implements WebMvcConfigurer {
-
- @Autowired
- private RepeatSubmitInterceptor repeatSubmitInterceptor;
-
- /**
- * 自定义拦截规则
- */
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。