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);
    }