1、定義一個介面用來控制限制的時間 package org.jeecg.common.aspect.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import ...
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); }