首页 > 编程语言 >java 接口限制访问次数

java 接口限制访问次数

时间:2022-11-25 18:23:41浏览次数:38  
标签:count map java request 接口 次数 limitRequest LimitRequest

1. 通过注解的形式实现通用接口访问次数限制

(1)pom.xml文件中引入expiringmap

 <dependency>
      <groupId>net.jodah</groupId>
      <artifactId>expiringmap</artifactId>
      <version>0.5.10</version>
 </dependency>

(2)添加注解

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LimitRequest {
    //请求时间
    long time() default 60 * 1000;
    //请求次数
    int count() default Integer.MAX_VALUE;
}

(3)添加注解对应解析类

@Aspect
@Component
public class LimitRequestAspect {
    private static ConcurrentHashMap<String, ExpiringMap<String, Integer>> hashMap = new ConcurrentHashMap<>();

    @Pointcut("@annotation(limitRequest)")
    public void excudeService(LimitRequest limitRequest) {
    }

    @Around("excudeService(limitRequest)")
    public Object doAround(ProceedingJoinPoint pjp, LimitRequest limitRequest) throws Throwable {

        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        ExpiringMap<String, Integer> map = hashMap.getOrDefault(request.getRequestURI(), ExpiringMap.builder().variableExpiration().build());
        Integer count = map.getOrDefault(request.getRemoteAddr(), 0);

        if (count >= limitRequest.count()) {
            throw new BusinessException(500, "访问次数超过限制");
        } else if (count == 0) {
            map.put(request.getRemoteAddr(), count + 1, ExpirationPolicy.CREATED, limitRequest.time(), TimeUnit.MILLISECONDS);
        } else {
            map.put(request.getRemoteAddr(), count + 1);
        }
        hashMap.put(request.getRequestURI(), map);
        Object result = pjp.proceed();

        return result;
    }
}

然后就可以在接口上添加对应的注解@LimitRequest(time=60*1000, count = 3) 来限制时间范围内请求次数了。

2. 针对特殊接口

思路:通过redis 失效时间来控制时间范围内请求次数

String commentKey = String.format("comment:%d:%d", comment.getBusinessId(), comment.getUserId());
Long count = redisTemplate.opsForValue().increment(commentKey);
if (count > 10) {
     throw new BusinessException("发表评论过于频繁,休息下再操作吧~");
   }
redisTemplate.expire(commentKey, 30, TimeUnit.SECONDS);

 

标签:count,map,java,request,接口,次数,limitRequest,LimitRequest
From: https://www.cnblogs.com/wlong-blog/p/16925999.html

相关文章

  • JavaWeb知识总结
    HTML是什么:HyperTextMarkerLanguage超文本标记语言超文本:超级文本例如流媒体、声音、图片等标签:这种语言有大量的标签组成任何一个标签都有开始标签和结束标签开......
  • java学习笔记
    定义数组1.整形数组,charfloatdouble等和int格式相同int[]<数组名>=newint[needsize]; 2.定义字符串数组String<数组名>;<数组名>={"littleshark!"}; ......
  • java出现javax/xml/bind/DatatypeConverter错误
     今天在使用Jwt生成token的时候出现的错误,错误如下:Exceptioninthread"main"java.lang.NoClassDefFoundError:javax/xml/bind/DatatypeConverter atio.jsonwebtoken......
  • JAVA数据类型-占用字节
    数据类型 数值类型整数 byte占1个字节范围:-128~127 short占2个字节范围:-32768~32767 int占4个字节范围:-2147483648~2147483647 long占8个字节浮点 float占4个......
  • 资深java面试题及答案整理(四)
     资深java面试题及答案整理(四)7.编写Java程序时,如何在Java中创建死锁并修复它?经典但核心Java面试问题之一。如果你没有参与过多线程并发Java应用程序的编码,你......
  • 精通正则表达式- JavaScript的实现和应用
    1.正则表达式对象模式/pattern/flagspattern是任何简单或复杂的正则表达式,可以包含字符类,限定符,分组,向前查找以及反向引用。flags是匹配模式标明正则表达式的......
  • 资深java面试题及答案整理(五)
     8.如果你的Serializable类包含一个不可序列化的成员,会发生什么?你是如何解决的?任何序列化该类的尝试都会因NotSerializableException而失败,但这可以通过在Java中为st......
  • JavaScript 基础
    JavaScript使用JS的几种写法行内式的js直接写道元素的内部​​<buttontype="button"value="须弥"onclick="alert('纳西妲')"></button>​​内嵌式js引入式​​<scripts......
  • Java 注解与反射 基础
    注解与反射基础什么是注解Annotation注解Annotation的作用:不是程序本身,可以对程序做出解释。可以被其他程序(比如编译器等)读取annotation的格式:注解是以”@注释名“再代......
  • Java高效找出两个大数据量List集合中的不同元素
    本文将带你了解如何快速的找出两个相似度非常高的List集合里的不同元素。主要通过JavaAPI、List集合双层遍历比较不同、借助Map集合查找三种方式,以及他们之间的执行效率情......