1、添加依赖
<dependency> <groupId>net.jodah</groupId> <artifactId>expiringmap</artifactId> <version>0.5.10</version> </dependency>
2、新建注解
package com.qax.situation.transmission.application.annoation; import java.lang.annotation.*; @Documented @Target(ElementType.METHOD) // 说明该注解只能放在方法上面 @Retention(RetentionPolicy.RUNTIME) public @interface LimitRequest { long time() default 60000; // 限制时间 单位:毫秒 int count() default Integer.MAX_VALUE; // 允许请求的次数 }
3、自定义AOP切面
package com.qax.situation.transmission.application.annoation; import com.qax.needle.common.constant.HttpStatus; import com.qax.needle.framework.boot.exception.BaseException; import net.jodah.expiringmap.ExpirationPolicy; import net.jodah.expiringmap.ExpiringMap; 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.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.ConcurrentHashMap; import java.util.concurrent.TimeUnit; @Aspect @Component public class LimitRequestAspect { private static ConcurrentHashMap<String, ExpiringMap<String, Integer>> book = new ConcurrentHashMap<>(); // 定义切点 // 让所有有@LimitRequest注解的方法都执行切面方法 @Pointcut("@annotation(limitRequest)") public void excudeService(LimitRequest limitRequest) { } @Around("excudeService(limitRequest)") public Object doAround(ProceedingJoinPoint pjp, LimitRequest limitRequest) throws Throwable { // 获得request对象 RequestAttributes ra = RequestContextHolder.getRequestAttributes(); ServletRequestAttributes sra = (ServletRequestAttributes) ra; HttpServletRequest request = sra.getRequest(); // 获取Map对象, 如果没有则返回默认值 // 第一个参数是key, 第二个参数是默认值 ExpiringMap<String, Integer> uc = book.getOrDefault(request.getRequestURI(), ExpiringMap.builder().variableExpiration().build()); Integer nowCount = uc.getOrDefault(request.getRemoteAddr(), 0); if (nowCount >= limitRequest.count()) { // 超过次数,不执行目标方法 throw new BaseException(HttpStatus.PERMISSION_DENIED, "", "接口请求超过次数"); //return JsonResult.error("请求次数过多,已经限制"); } else if (nowCount == 0) { // 第一次请求时,设置有效时间 // /** Expires entries based on when they were last accessed */ // ACCESSED, // /** Expires entries based on when they were created */ // CREATED; uc.put(request.getRemoteAddr(), nowCount + 1, ExpirationPolicy.CREATED, limitRequest.time(), TimeUnit.MILLISECONDS); } else { // 未超过次数, 记录加一 uc.put(request.getRemoteAddr(), nowCount + 1); } book.put(request.getRequestURI(), uc); // result的值就是被拦截方法的返回值 return pjp.proceed(); } }
4、在函数上添加注解
@LimitRequest(count = 10)
原文地址:http://www.cnblogs.com/shangwei/p/16783792.html
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,请务用于商业用途!
3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员!
8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载
声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性