Springboot使用redis进行api防刷限流过程详解

网友投稿 426 2023-07-06

Springboot使用redis进行api防刷限流过程详解

Springboot使用redis进行api防刷限流过程详解

这篇文章主要介绍了Springboot使用redis进行api防刷限流过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

api限流的场景

限流的需求出现在许多常见的场景中

秒杀活动,有人使用软件恶意刷单抢货,需要限流防止机器参与活动

某api被各式各样系统广泛调用,严重消耗网络、内存等资源,需要合理限流

api限流实战

首先我们编写注解类AccessLimit,使用注解方式在方法上限流更优雅更方便!三个参数分别代表有效时间、最大访问次数、是否需要登录,可以理解为 seconds 内最多访问 maxCount 次。

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 {

int seconds();

int maxCount();

boolean needLogin() default true;

}

限流的思路

通过路径:ip的作为key,访问次数为value的方式对某一用户的某一请求进行唯一标识

每次访问的时候判断key是否存在,是否count超过了限制的访问次数

若访问超出限制,则应response返回msg:请求过于频繁给前端予以展示

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;

@Component

public class AccessLimtInterceptor implements HandlerInterceptor {

@Autowired

private RedisService 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 (null == accessLimit) {

return true;

}

int seconds = accessLimit.seconds();

int maxCount = accessLimit.maxCount();

boolean needLogin = accessLimit.needLogin();

if (needLogin) {

//判断是否登录

}

String key = rhttp://equest.getContextPath() + ":" + request.getServletPath() + ":" + ip ;

Integer count = redisService.get(key);

if (null == count || -1 == count) {

redisService.set(key, 1);

redisService.expire(seconds);

return true;

}

if (count < maxCount) {

redisService.inCr(key);

return true;

}

if (count >= maxCount) {

// response 返回 json 请求过于频繁请稍后再试

return false;

}

}

return true;

}

}

注册-并配置拦截路径和不拦截路径

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;

// extends WebMvcConfigurerAdapter 已经废弃,java 8开始直接继承就可以

@Configuration

public class IntercepterConfig implements WebMvcConfigurer {

@Autowired

private AccessLimtInterceptor accessLimtInterceptor;

@Override

public void addInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(accessLimtInterceptor)

.addPathPatterns("/拦截路径")

.excludePathPatterns("/不被拦截路径 通常为登录注册或者首页");

}

}

在Controller层的方法上直接可以使用注解@AccessLimit

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

@RequestMapping("test")

public class TestControler {

@GetMapping("acciXlYWYTqessLimit")

@AccessLimit(seconds = 3, maxCount = 10)

public String testAccessLimit() {

//xxxx

return "";

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Spring Boot中@ConditionalOnProperty的使用方法
下一篇:spring security获取用户信息的实现代码
相关文章

 发表评论

暂时没有评论,来抢沙发吧~