1、自定义一个注解类
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AcctessLimit {
long second() default 5L;
long maxTime() default 3L;
long bidDenTime() default 60L;
}
2、编写自定义过滤器实现HandlerInterceptor类
@Slf4j
@Component
public class AccessLimintInterceptor implements HandlerInterceptor {
private RedisTemplate redisTemplate;
@Autowired
public AccessLimintInterceptor(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
public static final String LOCK_PREFIX = "INTERFACE_LOCK";
public static final String COUNT_PREFIX = "INTERFACE_COUNT";
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if(handler instanceof HandlerMethod){
HandlerMethod targetMethod = (HandlerMethod) handler;
AcctessLimit accessLimit = targetMethod.getMethod().getAnnotation(AcctessLimit.class);
if(!Objects.isNull(accessLimit)){
String ip = request.getRemoteAddr();
String uri = request.getRequestURI();
String lockKey = LOCK_PREFIX + ip + uri;
Object isLock = redisTemplate.opsForValue().get(lockKey);
if (Objects.isNull(isLock)) {
String countKey = COUNT_PREFIX + ip + uri;
Object count = redisTemplate.opsForValue().get(countKey);
long second = accessLimit.second();
long maxTime = accessLimit.maxTime();
if (Objects.isNull(count)) {
log.info("第一次访问");
redisTemplate.opsForValue().set(countKey, 1, second, TimeUnit.SECONDS);
} else {
if ((Integer) count < maxTime) {
redisTemplate.opsForValue().increment(countKey);
} else {
log.info("{}禁用访问此路径:{}", ip, uri);
long forbiddenTime = accessLimit.bidDenTime();
redisTemplate.opsForValue().set(lockKey, 1, forbiddenTime, TimeUnit.SECONDS);
redisTemplate.delete(countKey);
throw new ApiException("接口访问超限,请稍后尝试");
}
}
} else {
throw new ApiException("接口访问超限,请稍后尝试");
}
}
}
return true;
}
}
3、添加过滤器到应用
@Configuration
public class WebFilterConfig implements WebMvcConfigurer {
private AccessLimintInterceptor accessLimintInterceptor;
@Autowired
public WebFilterConfig(AccessLimintInterceptor accessLimintInterceptor) {
this.accessLimintInterceptor = accessLimintInterceptor;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(accessLimintInterceptor).addPathPatterns("/**");
}
}