定義注解
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進(jìn)行判斷
//.......
// key+=""+"1"; //用戶id userId
}
//從redis中獲取用戶訪問的次數(shù)
// 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{
//超出訪問次數(shù)
System.out.println(key+":訪問次數(shù)超多!!!");
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