赞
踩
通过拦截器拦截需要防重复添加的url接口,通过 历史的key:value,获取历史key的value值与当前valueNew检验,相同,提示重复提交
key :用户(或者token)+url(请求接口)
value:请求的内容(params + data)数据
@SameUrlData 的 value 默认 3秒内不允许重复提交相同数据
可以自定义
1、自定义注解 SameUrlData
自定义注解防止表单重复提交
- package org.springblade.common.sameUrlData;
-
- import java.lang.annotation.*;
-
- /**
- * * 自定义注解防止表单重复提交
- */
- @Inherited
- @Target(ElementType.METHOD)
- @Retention(RetentionPolicy.RUNTIME)
- @Documented
- public @interface SameUrlData {
- /**
- * 默认 3 秒不允许 重复新增
- * @return
- */
- long value() default 3L;
-
- }
2、注册拦截器 WebMvcConfigExt =》WebMvcConfigurer
- package org.springblade.common.sameUrlData;
-
- 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;
-
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- * * 注册拦截器
- */
- @Configuration
- public class WebMvcConfigExt implements WebMvcConfigurer {
-
- /**
- * 防止重复提交拦截器
- */
- @Autowired
- private SameUrlDataInterceptor sameUrlDataInterceptor;
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- // 避开静态资源
- List<String> resourcePaths = defineResourcePaths();
- registry.addInterceptor(sameUrlDataInterceptor).addPathPatterns("/**").excludePathPatterns(resourcePaths);// 重复请求
- }
-
- /**
- * 自定义静态资源路径
- *
- * @return
- */
- public List<String> defineResourcePaths() {
- List<String> patterns = new ArrayList<>();
- patterns.add("/assets/**");
- patterns.add("/upload/**");
- patterns.add("/error");
- return patterns;
- }
- }
3、防止用户重复提交数据拦截器 SameUrlDataInterceptor =》HandlerInterceptorAdapter
- package org.springblade.common.sameUrlData;
-
- import com.alibaba.fastjson.JSONObject;
- import com.baomidou.mybatisplus.core.toolkit.StringUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springblade.core.redis.cache.BladeRedis;
- import org.springblade.core.secure.utils.AuthUtil;
- import org.springblade.core.tool.utils.SpringUtil;
- import org.springframework.stereotype.Component;
- import org.springframework.web.method.HandlerMethod;
- import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.lang.reflect.Method;
-
- /**
- * * 防止用户重复提交数据拦截器
- */
- @Component
- public class SameUrlDataInterceptor extends HandlerInterceptorAdapter {
- private static Logger LOG = LoggerFactory.getLogger(SameUrlDataInterceptor.class);
-
- private static BladeRedis bladeRedis;
-
- public static BladeRedis getBladeRedis() {
- if (bladeRedis == null) {
- bladeRedis = SpringUtil.getBean(BladeRedis.class);
- }
- return bladeRedis;
- }
-
- /**
- * * 是否阻止提交,fasle阻止,true放行
- * * @return
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- if (handler instanceof HandlerMethod) {
- HandlerMethod handlerMethod = (HandlerMethod) handler;
- Method method = handlerMethod.getMethod();
- SameUrlData annotation = method.getAnnotation(SameUrlData.class);
- if (annotation != null) {
- if (repeatDataValidator(request,annotation.value())) {
- //请求数据相同
- LOG.warn("please don't repeat submit,url:" + request.getServletPath());
- JSONObject result = new JSONObject();
- result.put("code", "400");
- result.put("msg", "请勿重复请求");
- result.put("success", "false");
- response.setCharacterEncoding("UTF-8");
- response.setContentType("application/json; charset=utf-8");
- response.getWriter().write(result.toString());
- response.getWriter().close();
- // 拦截之后跳转页面
- // String formRequest = request.getRequestURI();
- // request.setAttribute("myurl", formRequest);
- // request.getRequestDispatcher("/WebRoot/common/error/jsp/error_message.jsp").forward(request, response);
- return false;
- } else {//如果不是重复相同数据
- return true;
- }
- }
- return true;
- } else {
- return super.preHandle(request, response, handler);
- }
- }
-
- /**
- * 验证同一个url数据是否相同提交,相同返回true
- *
- * @param httpServletRequest
- * @return
- */
- public boolean repeatDataValidator(HttpServletRequest httpServletRequest,Long seconds) throws IOException {
- BufferedReader streamReader = new BufferedReader(new InputStreamReader(httpServletRequest.getInputStream(), "UTF-8"));
- StringBuilder sb = new StringBuilder();
- String inputStr;
- while ((inputStr = streamReader.readLine()) != null) {
- sb.append(inputStr);
- }
- System.out.println("data===========" + sb.toString());
-
- String params = httpServletRequest.getQueryString();
- //获取请求参数map
-
- String token = AuthUtil.getUserId().toString();
-
- System.out.println("params===========" + params);
-
- String keyNew = (StringUtils.isBlank(params) ? "" : params) + "|" + (StringUtils.isBlank(sb.toString()) ? "" : sb.toString());
-
- String url = httpServletRequest.getRequestURI();
-
- String redisKey = "url:user:" + token + ":" + url;
- String preUrlParams = getBladeRedis().get(redisKey);
- if (StringUtils.isBlank(preUrlParams)) {
- //如果上一个数据为null,表示还没有访问页面
- //存放并且设置有效期,2秒
- getBladeRedis().setEx(redisKey, keyNew, seconds);
- return false;
- } else {//否则,已经访问过页面
- if (preUrlParams.equals(keyNew)) {
- //如果上次url+数据和本次url+数据相同,则表示重复添加数据
- return true;
- } else {//如果上次 url+数据 和本次url加数据不同,则不是重复提交
- getBladeRedis().setEx(redisKey, preUrlParams, seconds);
- return false;
- }
- }
- }
- }
4、MVC 方法添加注解 @SameUrlData(value = 20L)
- /**
- * 新增 采购收货(检验收货)
- */
- @SameUrlData(value = 20L)
- @PostMapping("/savePurchaseDeliveryVO")
- @ApiOperationSupport(order = 4)
- @ApiOperation(value = "新增 采购收货(检验收货)", notes = "传入purchaseDelivery")
- public R<PurchaseDeliveryVO> savePurchaseDeliveryVO(@Valid @RequestBody PurchaseDeliveryVO purchaseDelivery) {
- return R.data(purchaseDeliveryService.savePurchaseDeliveryVO(purchaseDelivery));
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。