Java 处理重复提交问题
1、定义一个注解用来控制限制的时间
package org.jeecg.common.aspect.annotation; 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; /** * @author 作者 :Tring * @version 创建时间:2022年5月10日 下午6:25:17 * 类说明 处理重复提交问题 */ @Inherited @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface NoRepeatSubmit { /** * 默认1s钟以内算重复提交 * @return */ long timeout() default 1; }
2、配置切面拦截所有请求
package org.jeecg.common.aspect; import java.lang.reflect.Method; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.jeecg.common.api.vo.Result; import org.jeecg.common.aspect.annotation.NoRepeatSubmit; import org.jeecg.common.constant.PublicHeaderParameter; import org.jeecg.common.util.RedisUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import me.zhyd.oauth.utils.IpUtils; /** * @author 作者 :Tring * @version 创建时间:2022年5月10日 下午6:26:36 * * 类说明 aop切面注解控制指定接口不能重复提交 * 实现原理 请求拦截,通过IP+token+请求地址为key存Redis,Redis若存在则弹出异常 * 使用例子 在想要拦截的接口上面加入@NoRepeatSubmit自定义注解即系 */ @Aspect @Component public class NoRepeatSubmitAop { @Autowired private RedisUtil redisService; /** * 切入点 */ @Pointcut("@annotation(org.jeecg.common.aspect.annotation.NoRepeatSubmit)") public void pt() { } @Around("pt()") public Object arround(ProceedingJoinPoint joinPoint) throws Throwable { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); assert attributes != null; HttpServletRequest request = attributes.getRequest(); // 获取注解 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); NoRepeatSubmit annotation = method.getAnnotation(NoRepeatSubmit.class); //获取请求IP String IP = IpUtils.getLocalIp(); //获取token String token = request.getHeader(PublicHeaderParameter.X_ACCESS_TOKEN); //这里是唯一标识 根据情况而定 String key = IP + "-" + token + "-" + request.getServletPath(); // 如果缓存中有这个url视为重复提交 if (!redisService.hasKey(key)) { //通过,执行下一步 Object o = joinPoint.proceed(); //然后存入redis 并且设置1s倒计时 redisService.set(key, 0, annotation.timeout(), TimeUnit.SECONDS); //返回结果 return o; } else { return Result.error(500, "请勿重复提交或者操作过于频繁!"); } } }
3、在需要加限制重复操作的地方加上@NoRepeatSubmit 注解
/** * 用户投票 */ @RequestMapping(value = "/setPollReply/{version}", method = RequestMethod.POST) @ApiVersion(2) @NoRepeatSubmit public Result<?> setPollReply( HttpServletRequest request,@RequestBody EbCorporatePollReply PollReply) { return pollCampaignService.setPollReply(request,PollReply); }