天天看點

java 分布式 重複送出_springboot分布式重複送出解決方案

問題:使用者端有時候送出資訊時會短時間内重複點選好幾次,此時前端可以做相應處理進行攔截。但是後端也得做相應的處理,需要過濾同一使用者短時間内對同一接口的多次請求。

背景:springboot的java項目+分布式伺服器架構

方案概述:首先采用redis作為緩存來應對分布式伺服器的不同請求。其次采用spring自帶的切面功能在需要攔截重複請求的方法上進行注解。

代碼:

這裡是具體的防止重複送出的代碼,通過 @Around("@annotation(com.dazhi.common.aop.NoRepeatSubmitAop)")一行綁定注解類。

不懂切點原理的見aop切點文法

@Aspect

@Component

public class NoRepeatSubmitAop {

private static final Loggerlogger = LoggerFactory.getLogger(ControllerAspect.class);

@Autowired

private StringRedisTemplatestringRedisTemplate;

@Around("@annotation(com.dazhi_park.common.aop.NoRepeatSubmitAop)")

public Objectarround(ProceedingJoinPoint pjp) {

RespJsonObject object =new RespJsonObject();

logger.info("攔截請求!!!!!!!!!!!!");

try {

RequestAttributes ra = RequestContextHolder.getRequestAttributes();

ServletRequestAttributes sra = (ServletRequestAttributes) ra;

HttpServletRequest request = sra.getRequest();

String uri = request.getRequestURI();

String rdsession = request.getParameter("rdsession");

String key = rdsession +"-" + uri;

if (stringRedisTemplate.opsForValue().get(key) ==null) {// 如果緩存中有這個url視為重複送出

Object o = pjp.proceed();

stringRedisTemplate.opsForValue().set(key, "0", 5, TimeUnit.SECONDS);

return o;

}else {

logger.info("重複送出");

object.setRespCode("40000");

object.setRespMessage("重複送出");

return object;

}

}catch (Throwable e) {

logger.info("送出次數過多");

object.setSuccess();

return object;

}

}

}

這是注解類

@Target(ElementType.METHOD) // 作用到方法上

@Retention(RetentionPolicy.RUNTIME) // 運作時有效

public @interface NoRepeatSubmitAop {

}

之後在需要的方法上加上注解就好。