分布式限流--基于Spring

1 实现方式:

自定义注解+拦截器+Redis实现限流 (单体和分布式均适用,全局限流)

##############################################################################################

下面开始编码

2 自定义注解:

@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Limiter {
   int limit() default 10;
   int sec() default 10;
}

3 拦截器:

public class LimitInterceptor implements HandlerInterceptor {
 @Autowired
 private RedisTemplate<String, Integer> redisTemplate; //使用RedisTemplate操作redis
 @Override
 public boolean preHandle(HttpServletRequest request, HttpServletResponse response,   Object handler) 
 throws Exception {
  if (handler instanceof HandlerMethod) {
     HandlerMethod handlerMethod = (HandlerMethod) handler;
     Method method = handlerMethod.getMethod();
     if (!method.isAnnotationPresent(Limiter.class)) {
         return true;
     }
     Limiter limiter = method.getAnnotation(Limiter.class);
     if (limiter == null) {
         return true;
     }
     int limit = limiter.limit();
     int sec = limiter.sec();
     String key = IPUtil.getIpAddr(request) + request.getRequestURI();
     Integer maxLimit = redisTemplate.opsForValue().get(key);
     if (maxLimit == null) {
         redisTemplate.opsForValue().set(key, 1, sec, TimeUnit.SECONDS); //set时一定要加过期时间
     } else if (maxLimit < limit) {
         redisTemplate.opsForValue().set(key, maxLimit + 1, sec, TimeUnit.SECONDS);
     } else {
         output(response, "请求太频繁!");
         return false;
     }
  }
  return true;
 }
 
 public void output(HttpServletResponse response, String msg) throws IOException {
     response.setContentType("application/json;charset=UTF-8");
     ServletOutputStream outputStream = null;
     try {
         outputStream = response.getOutputStream();
         outputStream.write(msg.getBytes("UTF-8"));
     } catch (IOException e) {
       e.printStackTrace();
     } finally {
       outputStream.flush();
       outputStream.close();
     }
 }
 
 @Override
 public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, 
 ModelAndView modelAndView) throws Exception {
 
 }
 
 @Override
 public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
  Exception ex) throws Exception {
 
 }
 
}

4 controller:

@Controller
@RequestMapping("/study")
public class limitController {
    @ResponseBody
    @RequestMapping("/test")
    @Limiter(limit = 10,sec = 100) //加上自定义注解即可
    public String test (HttpServletRequest request,@RequestParam(value = "username",required = false)
     String userName){
        //TODO somethings……
        return "hello world !";
    }
}

5 配置文件

/*springmvc的配置文件中加入自定义拦截器*/
<mvc:interceptors>
 <mvc:interceptor>
 <mvc:mapping path="/**"/>
 <bean class="com.study.controller.limit.LimitInterceptor/>
 </mvc:interceptor>
</mvc:interceptors>

6 测试

使用PostMan工具就可以对我们的接口进行测试。

参考:https://github.com/crossoverJie/distributed-redis-tool

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值