問題:使用者端有時候送出資訊時會短時間内重複點選好幾次,此時前端可以做相應處理進行攔截。但是後端也得做相應的處理,需要過濾同一使用者短時間内對同一接口的多次請求。
背景: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 {
}
之後在需要的方法上加上注解就好。