当前位置:   article > 正文

Spring Boot 防止重复提交_springboot防重复提交

springboot防重复提交

若依方案

实现思路:

1.将请求的url作为key,参数和时间作为内容存到Redis中;

2.再次发起请求时,根据url查询缓存信息,比较参数和时间;

3.若同一url请求参数相同且在指定时间内,认为它为重复请求,进行拦截。

1.自定义注解

  1. import java.lang.annotation.Documented;
  2. import java.lang.annotation.ElementType;
  3. import java.lang.annotation.Inherited;
  4. import java.lang.annotation.Retention;
  5. import java.lang.annotation.RetentionPolicy;
  6. import java.lang.annotation.Target;
  7. /**
  8. * 自定义注解防止表单重复提交
  9. */
  10. @Inherited
  11. @Target(ElementType.METHOD)
  12. @Retention(RetentionPolicy.RUNTIME)
  13. @Documented
  14. public @interface RepeatSubmit {
  15. /**
  16. * 间隔时间(ms),小于此时间视为重复提交
  17. */
  18. public int interval() default 5000;
  19. /**
  20. * 提示消息
  21. */
  22. public String message() default "不允许重复提交,请稍候再试";
  23. }

2.定义防止重复提交的拦截器

  1. import java.lang.reflect.Method;
  2. import javax.servlet.http.HttpServletRequest;
  3. import javax.servlet.http.HttpServletResponse;
  4. import com.mcs.repeatsubmit.annotation.RepeatSubmit;
  5. import com.mcs.repeatsubmit.core.AjaxResult;
  6. import com.mcs.repeatsubmit.core.ServletUtils;
  7. import org.springframework.stereotype.Component;
  8. import org.springframework.web.method.HandlerMethod;
  9. import org.springframework.web.servlet.HandlerInterceptor;
  10. import com.alibaba.fastjson2.JSON;
  11. /**
  12. * 防止重复提交拦截器
  13. *
  14. * @author ruoyi
  15. */
  16. @Component
  17. public abstract class RepeatSubmitInterceptor implements HandlerInterceptor {
  18. @Override
  19. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  20. if (handler instanceof HandlerMethod) {
  21. HandlerMethod handlerMethod = (HandlerMethod) handler;
  22. Method method = handlerMethod.getMethod();
  23. RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
  24. if (annotation != null) {
  25. if (this.isRepeatSubmit(request, annotation)) {
  26. AjaxResult ajaxResult = AjaxResult.error(annotation.message());
  27. ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
  28. return false;
  29. }
  30. }
  31. }
  32. return true;
  33. }
  34. /**
  35. * 验证是否重复提交由子类实现具体的防重复提交的规则
  36. *
  37. * @param request
  38. * @return
  39. * @throws Exception
  40. */
  41. public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
  42. }

3.具体方法实现

  1. import java.util.HashMap;
  2. import java.util.Map;
  3. import java.util.concurrent.TimeUnit;
  4. import javax.servlet.http.HttpServletRequest;
  5. import com.mcs.repeatsubmit.annotation.RepeatSubmit;
  6. import com.mcs.repeatsubmit.core.CacheConstants;
  7. import com.mcs.repeatsubmit.core.HttpHelper;
  8. import com.mcs.repeatsubmit.core.RedisCache;
  9. import com.mcs.repeatsubmit.filter.RepeatedlyRequestWrapper;
  10. import org.apache.commons.lang3.StringUtils;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.beans.factory.annotation.Value;
  13. import org.springframework.stereotype.Component;
  14. import com.alibaba.fastjson2.JSON;
  15. /**
  16. * 判断请求url和数据是否和上一次相同,
  17. * 如果和上次相同,则是重复提交表单。 有效时间为10秒内。
  18. */
  19. @Component
  20. public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
  21. public final String REPEAT_PARAMS = "repeatParams";
  22. public final String REPEAT_TIME = "repeatTime";
  23. // 令牌自定义标识
  24. @Value("${token.header}")
  25. private String header;
  26. @Autowired
  27. private RedisCache redisCache;
  28. @SuppressWarnings("unchecked")
  29. @Override
  30. public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation) {
  31. String nowParams = "";
  32. if (request instanceof RepeatedlyRequestWrapper) {
  33. RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
  34. nowParams = HttpHelper.getBodyString(repeatedlyRequest);
  35. }
  36. // body参数为空,获取Parameter的数据
  37. if (StringUtils.isEmpty(nowParams)) {
  38. nowParams = JSON.toJSONString(request.getParameterMap());
  39. }
  40. Map<String, Object> nowDataMap = new HashMap<String, Object>();
  41. nowDataMap.put(REPEAT_PARAMS, nowParams);
  42. nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
  43. // 请求地址(作为存放cache的key值)
  44. String url = request.getRequestURI();
  45. // 唯一值(没有消息头则使用请求地址)
  46. String submitKey = StringUtils.trimToEmpty(request.getHeader(header));
  47. // 唯一标识(指定key + url + 消息头)
  48. String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
  49. Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
  50. if (sessionObj != null) {
  51. Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
  52. System.out.println(sessionMap);
  53. if (sessionMap.containsKey(url)) {
  54. Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
  55. if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap,
  56. annotation.interval())) {
  57. return true;
  58. }
  59. }
  60. }
  61. Map<String, Object> cacheMap = new HashMap<String, Object>();
  62. cacheMap.put(url, nowDataMap);
  63. redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS);
  64. return false;
  65. }
  66. /**
  67. * 判断参数是否相同
  68. */
  69. private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap) {
  70. String nowParams = (String) nowMap.get(REPEAT_PARAMS);
  71. String preParams = (String) preMap.get(REPEAT_PARAMS);
  72. return nowParams.equals(preParams);
  73. }
  74. /**
  75. * 判断两次间隔时间
  76. */
  77. private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval) {
  78. long time1 = (Long) nowMap.get(REPEAT_TIME);
  79. long time2 = (Long) preMap.get(REPEAT_TIME);
  80. if ((time1 - time2) < interval) {
  81. return true;
  82. }
  83. return false;
  84. }
  85. }

4.添加拦截器

  1. import org.springframework.beans.factory.annotation.Autowired;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
  4. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  5. @Configuration
  6. public class ResourcesConfig implements WebMvcConfigurer {
  7. @Autowired
  8. private RepeatSubmitInterceptor repeatSubmitInterceptor;
  9. /**
  10. * 自定义拦截规则
  11. */
  12. @Override
  13. public void addInterceptors(InterceptorRegistry registry) {
  14. registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
  15. }
  16. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/234281
推荐阅读
相关标签
  

闽ICP备14008679号