spring boot使用redis限制接口访问次数
程序员文章站
2022-03-19 16:01:41
spring boot使用redis限制接口访问次数...
首先自定义一个注解用于需要限制访问次数的接口
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequestLimit {
//限制访问次数
int limitCount() default 3;
//超时时间
long expireTime() default 60L;
//请求url
String requestUrl() default "";
}
切面用于执行具体的操作
@Component
@Aspect
public class RequestLimitAspect {
@Autowired
private RedisUtils redisUtils;
@Pointcut("@annotation(requestLimit)")
public void limit(RequestLimit requestLimit) {
}
@Around("limit(requestLimit)")
public Object requestLimitLog(ProceedingJoinPoint joinPoint, RequestLimit requestLimit) throws Throwable {
HttpServletRequest request = null;
HttpServletResponse response = null;
Object[] args = joinPoint.getArgs();
for (Object arg : args) {
if(arg instanceof HttpServletRequest)
request = (HttpServletRequest) arg;
if(arg instanceof HttpServletResponse)
response = (HttpServletResponse) arg;
}
if (request == null || response == null)
return null;
String sessionId = request.getSession().getId();
String key = sessionId + requestLimit.requestUrl();
long limitTime = requestLimit.expireTime();
//从redis获取值
Object requestCount = redisUtils.get(key);
//首次访问初始化请求次数及过期时间,后续访问时判断请求次数是否超过限制次数
if (requestCount == null) {
redisUtils.set(key, 1, limitTime);
} else if(Integer.valueOf(requestCount.toString()) >= requestLimit.limitCount()) {
//超过限制次数返回对应枚举值
LoginHandlerInterceptor.handlerErrorResponse(response, RetEnum.REQUEST_LIMITED);
return null;
} else {
//更新访问次数及过期时间
Integer count = Integer.valueOf(requestCount.toString()) + 1;
redisUtils.set(key, count, limitTime);
}
return joinPoint.proceed(args);
}
}
handlerErrorResponse方法用于返回错误信息
public static void handlerErrorResponse(HttpServletResponse response, RetEnum retEnum) throws Exception {
response.setStatus(200);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
try (PrintWriter writer = response.getWriter()) {
String result = "{\"state\": \""
.concat(retEnum.getCode().toString())
.concat("\",\"msg\": \"")
.concat(retEnum.getMsg())
.concat("\"}");
writer.write(result);
writer.flush();
} catch (Exception e) {
throw new Exception("系统异常!");
}
}
RetEnum枚举
public enum RetEnum {
/**
* 请求被限制
*/
REQUEST_LIMITED (1004,"请求被限制!"),
private Integer code;
private String msg;
RetEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public Integer getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
Controller
@RestController
public class HelloController {
@RequestLimit(requestUrl = "/hello")
@RequestMapping("/hello")
public String hello(@RequestParam String name, HttpServletRequest request, HttpServletResponse response) {
return "Hello " + name;
}
}
第1,2,3次执行结果
Hello test
第4次执行结果
{
"state": "1004",
"msg": "请求禁止!"
}
本文地址:https://blog.csdn.net/zt980995264/article/details/112009051