定义注解
import JAVA.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 接口防刷注解类
* @Author: Cyz
* @Description:
* @Date: create in 2022/6/28 16:55
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AccessLimit {
int seconds();
int maxCount();
boolean needLogin() default true;
}
编写接口防刷拦截器
import com.cyz.blog.utils.AccessLimit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
/**
* 接口防刷拦截器
* @Author: Cyz
* @Description:
* @Date: create in 2022/6/28 16:58
*/
@Component
public class AntiBrushInterceptor extends HandlerInterceptorAdapter {
@Autowired
private RedisTemplate redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//判断请求是否属于方法的请求
if(handler instanceof HandlerMethod){
HandlerMethod handlerMethod=(HandlerMethod) handler;
//获取方法中的注解,看是否有该注解
AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
if(accessLimit==null){
return true;
}
int seconds = accessLimit.seconds();
int maxcount = accessLimit.maxCount();
boolean login = accessLimit.needLogin();
String key = request.getRequestURI();
//如果需要登录
if(login){
//获取登录的session进行判断
//.......
// key+=""+"1"; //用户id userId
}
//从redis中获取用户访问的次数
// AccessKey ak = AccessKey.withExpire(seconds);
Integer count= (Integer)redisTemplate.opsForValue().get(key);
if(count==null){
//第一次访问
redisTemplate.opsForValue().set(key,1);
}else if(count<maxcount){
//加1
redisTemplate.opsForValue().set(key,(Integer)redisTemplate.opsForValue().get(key)+1,seconds, TimeUnit.SECONDS);
}else{
//超出访问次数
System.out.println(key+":访问次数超多!!!");
render(response,key+":请您休息片刻再试试!");
return false;
}
}
return true;
}
private void render(HttpServletResponse response, String message)throws Exception {
response.setContentType("Application/json;charset=UTF-8");
OutputStream out = response.getOutputStream();
String data = "{"code":501,"flag":false,"message":"+message+"}";
out.write(data.getBytes("UTF-8"));
out.flush();
out.close();
}
}
将拦截器注册到spring容器中
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* @Author: Cyz
* @Description:
* @Date: create in 2022/6/28 17:01
*/
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Autowired
private AntiBrushInterceptor interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interceptor);
}
}
controller接口编写
@AccessLimit(seconds = 5,maxCount = 5,needLogin = true)
接口防刷测试
参考原文:cyz