相同参数,一定时间内,重复请求拦截
主要代码如下:
RepeatRequest.java
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepeatRequest {
String value() default "";
}
RepeatRequestAspect.java
@Aspect
@Component
public class RepeatRequestAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(RepeatRequestAspect.class);
/**
* 执行切面拦截逻辑
*/
@Around("@annotation(repeatRequest)")
public Object execute(ProceedingJoinPoint joinPoint, RepeatRequest repeatRequest) throws Throwable {
if (repeatRequest != null) {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
StringBuffer sb=new StringBuffer("");
//1.获取参数
HttpServletRequest request=attributes.getRequest();
HttpServletResponse response=attributes.getResponse();
//ip
sb.append("ip:");
String ip = ToolUtil.getClientIp(request);
sb.append(ip);
//header
sb.append("head:");
Enumeration<String> headers=request.getHeaderNames();
while(headers.hasMoreElements()){
String heardName =headers.nextElement();
String heardValue= request.getHeader(heardName);
sb.append(heardName).append("=").append(heardValue).append(";");
}
//body
sb.append("body:");
Object[] args = joinPoint.getArgs();
for (int i = 0; i < args.length; i++) {
Object o = args[i];
sb.append(o.toString());
}
//2.所有 请求头、报文体 进行组装,查询redis 是否存在记录
LOGGER.info("sb="+sb.toString());
//sha 加密 、base64
QETag tag = new QETag();
String hash = tag.calcETag(sb.toString());
LOGGER.info("hash="+hash);
//存redis
String key = "request_key_" + hash;
String value=CacheUtils.get(key);
if(!StringUtil.isEmpty(value)){
//3.存在记录
//response.setStatus(304);
//怕摘要重复 可进行value处理,碰撞几率太小,可以忽略...
return RestResponse.failure("请勿重复请求");
}else{
//4.不存在记录,将所有参数组装写入redis,失效时间为3秒
CacheUtils.put(key, sb.toString(), 3);
}
}
return joinPoint.proceed();
}
}
tag.calcETag 其实就是 sha1 加密,然后再base64 -_-
就这样啦