java 自定义注解方式 实现限制接口请求次数
注解类RequestLimit
package com.cujia.user.common.annotation;
import java.lang.annotation.*;
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLimit {
long time() default 2000;
int count() default 1;
}
自定义切面RequestLimitAspect
package com.cujia.user.common.aop;
import com.cujia.user.common.DTO.Result;
import com.cujia.user.common.DTO.ResultCodeEnum;
import com.cujia.user.common.annotation.RequestLimit;
import net.jodah.expiringmap.ExpirationPolicy;
import net.jodah.expiringmap.ExpiringMap;
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.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
public class RequestLimitAspect {
private static ConcurrentHashMap<String, ExpiringMap> book = new ConcurrentHashMap<>();
@Pointcut("@annotation(requestLimit)")
public void excudeService(RequestLimit requestLimit) {
}
@Around("excudeService(requestLimit)")
public Result doAround(ProceedingJoinPoint proceedingJoinPoint, RequestLimit requestLimit) throws Throwable {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
ExpiringMap<String, Integer> expiringMap = book.getOrDefault(request.getRequestURI(), ExpiringMap.builder().variableExpiration().build());
Integer requestCount = expiringMap.getOrDefault(request.getRemoteAddr(), 0);
if (requestCount >= requestLimit.count()) {
return Result.fail(ResultCodeEnum.REQUEST_FREQUENCY_FAST);
} else if (requestCount == 0) {
expiringMap.put(request.getRemoteAddr(), requestCount + 1, ExpirationPolicy.CREATED, requestLimit.time(),
TimeUnit.MILLISECONDS);
} else {
expiringMap.put(request.getRemoteAddr(), requestCount + 1);
}
book.put(request.getRequestURI(), expiringMap);
Object result = proceedingJoinPoint.proceed();
return Result.success(result);
}
}
在接口方法上使用
@AllowDontLogIn
@ResponseBody
@ApiOperation("用户订阅类目列表")
@PostMapping("/getUserSubscribeList")
@RequestLimit(count = 2)
public Result<List<DbPushSubscribeVO>> getUserSubscribeList() {
return Result.ok(dbPushSubscribeBizService.getUserSubscribeList("0264b5ef04e944509eaf2f790119b800"));
}
连续请求两次结果