场景
SpringBoot搭建的项目需要对开放的接口进行防刷限制,不同接口指定多少秒内可以请求指定次数。
比如下方限制接口一秒内最多请求一次。
注:
博客:
https://blog.csdn.net/badao_liumang_qizhi
实现
1、实现思路
首先自定义注解,添加时间区间和最大请求次数字段。
然后自定义拦截器拦截方法上面是否有自定义的注解,如果有则获取请求的url,并作为redis中存储的key,区间区间即作为redis
的key的过期时间,每次请求累加次数并存储到redis中,判断在redis的key有效期内超过最大请求次数,则返回请求频繁的响应。
2、首先自定义注解实现
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface AccessLimit { /** * 秒数时间区间(多少秒内) * @return */ int seconds(); /** * 最大请求次数 * @return */ int maxCount(); }
3、然后自定义拦截实现HandlerInterceptor接口,并重写其preHandle方法,实现方法请求前的拦截
import com.alibaba.fastjson.JSON; import com.badao.demo.common.AjaxResult; import com.badao.demo.constant.Constants; import com.badao.demo.utils.RedisCache; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.OutputStream; import java.util.concurrent.TimeUnit; @Component public class FangshuaInterceptor implements HandlerInterceptor { @Autowired private RedisCache redisService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //判断请求是否属于方法的请求 if(handler instanceof HandlerMethod){ HandlerMethod hm = (HandlerMethod) handler; //获取方法中的注解,看是否有该注解 AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class); if(accessLimit == null){ return true; } int seconds = accessLimit.seconds(); int maxCount = accessLimit.maxCount(); //获取请求的Url作为redis中存储的key String key = request.getRequestURI(); //从redis中获取用户访问的次数 Integer count = redisService.getCacheObject(key); if(count == null){ //第一次访问 redisService.setCacheObject(key,1,seconds, TimeUnit.SECONDS); }else if(count < maxCount){ //加1 count+=1; redisService.setCacheObject(key,count,seconds, TimeUnit.SECONDS); }else{ //超出访问次数,则渲染响应结果 render(response); return false; } } return true; } /** * 接口渲染 * @param response * @throws Exception */ private void render(HttpServletResponse response)throws Exception { response.setContentType("application/json;charset=UTF-8"); OutputStream out = response.getOutputStream(); String str = JSON.toJSONString(AjaxResult.error(Constants.CALL_TOO_OFEN)); out.write(str.getBytes("UTF-8")); out.flush(); out.close(); } }
其中RedisCache是封装的操作redis的工具类
AjaxResult是封装的响应结果实体。
Constants.CALL_TOO_OFEN是常量类用来提示请求太频繁。
以上工具类的封装可以参考
若依前后端分离版手把手教你本地搭建环境并运行项目:
https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108465662
4、然后将intercepter注册到springboot中
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.WebMvcConfigurer; /** * 把intercepror 注册到springboot中 */ @Configuration public class WebConfig implements WebMvcConfigurer { @Autowired private FangshuaInterceptor interceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(interceptor); } }
5、使用时在接口方法上添加注解并指定时间和最大请求次数
@AccessLimit(seconds = 1,maxCount = 1) @GetMapping("/test") public AjaxResult test(@RequestParam("mineApiCode") String mineApiCode)
上面参数设置就是1秒内最大请求次数为1次。
标签:防刷,请求,自定义,接口,springframework,key,org,import,annotation From: https://www.cnblogs.com/badaoliumangqizhi/p/17387132.html