1、需要的依赖
<!-- redis依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- AOP依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> <!-- Map依赖 用redis就不需要了 --> <dependency> <groupId>net.jodah</groupId> <artifactId>expiringmap</artifactId> <version>0.5.8</version> </dependency>
2、定义注解
package org.springblade.modules.aspect.annotation; import java.lang.annotation.*; /** * 接口访问频率 * * @author * @date 2022/08/27 */ @Documented @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface InterfaceAccessRestriction { /** * 时间毫秒 单位:毫秒(默认:1分钟) * * @return long */ long time() default 60000; /** * 允许请求的次数 默认 5 * * @return int */ int value() default 30; }
3、切面实现
借助redis实现
package org.springblade.modules.aspect; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springblade.core.tool.api.R; import org.springblade.core.tool.api.ResultCode; import org.springblade.modules.aspect.annotation.InterfaceAccessRestriction; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.BoundHashOperations; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.util.concurrent.TimeUnit; /** * 接口访问频率 * * @author * @date 2022/08/27 */ @Aspect @Component @Slf4j public class InterfaceAccessRestrictionAspect { @Autowired private StringRedisTemplate redisTemplate; @Pointcut("@annotation(interfaceAccessRestriction)") public void controllerAspect(InterfaceAccessRestriction interfaceAccessRestriction) { } @Around(value = "controllerAspect(interfaceM)", argNames = "pjp,interfaceM") public Object doAround(ProceedingJoinPoint pjp, InterfaceAccessRestriction interfaceM) throws Throwable { RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes) ra; HttpServletRequest request = sra.getRequest(); BoundHashOperations<String, Object, Object> bho = redisTemplate.boundHashOps("blade:matrix:interfaceAccessRestriction" + request.getRequestURI()); String ipCnt = (String) bho.get(request.getRemoteAddr()); int uCount = ipCnt == null ? 0 : "".equals(ipCnt) ? 0 : Integer.parseInt(ipCnt); if (uCount >= interfaceM.value()) { log.error("接口拦截:{} 请求超过限制频率【{}次/{}ms】,IP为{}", request.getRequestURI(), interfaceM.value(), interfaceM.time(), request.getRemoteAddr()); R<?> r = new R<>(); r.setCode(ResultCode.FAILURE.getCode()); r.setMsg("刷新频率过高,请" + bho.getExpire() + "秒后再操作"); return r; } else { bho.increment(request.getRemoteAddr(), 1); bho.expire(interfaceM.time(), TimeUnit.MILLISECONDS); } return pjp.proceed(); } }
4、使用
5、效果
再结合自己的需求改改吧
借鉴博客:https://www.cnblogs.com/zys2019/p/16328053.html#_label0
标签:Spring,对接口,boot,request,springframework,interfaceM,import,org,annotation From: https://www.cnblogs.com/w-yu-chen/p/16630482.html