在一些场景下,需要防止接口被攻击或者因频繁被调用导致系统卡顿,此时限制接口的调用频率可以起到一定程度的缓和效果。

实现逻辑
定义注解,配置频率,放在需要限制调用频率的接口上。定义拦截器拦截注解,如果拦截到定义的注解,则设置redis值,key为ip+接口名称,value为调用次数,保存redis且设置保存时间为指定时间,如果值大于指定的值,拦截器不放行返回拦截信息,如果没有超过值则放行,redis的key不变,值加1。

1、定义注解
其中count为访问次数,time为指定时间

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import java.lang.annotation.*;@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
@Inherited
@Documented
@Order(Ordered.HIGHEST_PRECEDENCE) //最高优先级
public @interface RequestLimit {/**** 允许访问的次数,默认值MAX_VALUE*/int count() default Integer.MAX_VALUE;/**** 时间段,单位为毫秒,默认值一分钟*/long time() default 60000;
}

2、使用注解
如下在控制器上添加@RequestLimit(count = 2),标识默认时间内可以调用两次接口,默认时间为1分钟,即接口1分钟仅可以被调用两次

    @RequestMapping(value = {"getDocRecvCount"}@RequestLimit(count = 2)public OpenRespModel getCount(@RequestBody(required = false) OpenModel param) {return this.openService.getCount(param);}

3、拦截器配置
拦截到指定的注解,通过设置redis的数据,key为ip加上接口,value为已经调用的次数,redis数据有效时间为定义的时间

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com..commons.annotation.RequestLimit;
import com..commons.model.ResponseCodeEnum;
import com..util.RequestUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;
import java.util.concurrent.TimeUnit;public class RequestLimitInterceptor extends HandlerInterceptorAdapter {private static final Logger logger = LoggerFactory.getLogger("RequestLimitInterceptor");@Autowiredprivate RedisTemplate<String, String> redisTemplate;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//方法注解RequestLimit methodAnnotation = ((HandlerMethod) handler).getMethodAnnotation(RequestLimit.class);//类注解RequestLimit classAnnotation = ((HandlerMethod) handler).getBean().getClass().getAnnotation(RequestLimit.class);boolean vcode = true;if (methodAnnotation != null) {vcode = validateCode(request, methodAnnotation.count(), methodAnnotation.time());} else if (classAnnotation != null) {vcode = validateCode(request, classAnnotation.count(), classAnnotation.time());}if (vcode) {return true;} else {Map<String, Object> resultMap = Maps.newHashMap();resultMap.put("retCode", ResponseCodeEnum.REQUESTFULL.getRetCode());resultMap.put("retDesc", ResponseCodeEnum.REQUESTFULL.getRetDesc());try {response.setCharacterEncoding("UTF-8");response.setContentType("application/json;charset=UTF-8");PrintWriter pw = response.getWriter();pw.write(JSON.toJSONString(resultMap));pw.flush();pw.close();} catch (IOException e) {logger.error("返回页面数据出错!" + e.getMessage(), e);throw e;}return false;}}/*** 接口的访问频次限制** @param request* @return*/private boolean validateCode(HttpServletRequest request, int maxSize, long timeOut) {boolean resultCode = true;try {String ip = RequestUtil.getRemoteAddr(request);String url = request.getRequestURL().toString();String key = "req_limit_".concat(url).concat(ip);long count = redisTemplate.opsForValue().increment(key, 1);if (count == 1) {redisTemplate.expire(key, timeOut, TimeUnit.MILLISECONDS);}if (count > maxSize) {logger.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + maxSize + "]");resultCode = false;}} catch (Exception e) {logger.error("发生异常: ", e);}return resultCode;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

4、拦截器添加到项目中

 <!-- 拦截提供外部接口访问次数限制--><mvc:interceptor><mvc:mapping path="/openApi/**" /><bean class="com..commons.interceptor.RequestLimitInterceptor" /></mvc:interceptor>

第一,二次调用结果

第三次调用结果

过一分钟后等redis设置值失效后,便可以再次访问。

学海无涯苦作舟!!!

java 拦截器实现接口调用频率限制相关推荐

  1. Vue 拦截器 多接口调用 实现唯一loding效果 解决同步接口调用loding闪动

    大纲 1.引入`import axios from 'axios'` 2.创建loding函数`Loading.service`,创建计数变量`requestCount = 0`, 3.创建axios ...

  2. java拦截器项目应用_使用拦截器分析Java EE应用程序的性能下降/提高

    java拦截器项目应用 在开发具有某些性能要求的Java EE应用程序时,必须在每个发行版之前验证是否满足这些要求. 您可能会想到,哈德森的一项工作每天晚上在某些特定的硬件平台上执行一系列测试测量. ...

  3. 区分Java拦截器和过滤器

    今天带大家分析java拦截器和过滤器的区别,文中有非常详细的解释说明,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下 一.过滤器(filter) 过滤器处于客户端与Web资源(Serv ...

  4. JAVA拦截器(Interceptor)实现以及原码示例

    JAVA拦截器(Interceptor)实现以及原码示例 概念 SpringMVC中拦截器[interceptor] 一.实现拦截器代码 二.单/多 个拦截器运行 1.单个拦截器 2.多个拦截器 源码 ...

  5. Redis + Java拦截器实现用户匿名和非匿名访问

    文章目录 需求 实现截图 核心代码 WebMvcConfigurer HandlerInterceptor 判断用户是否有权限 ThreadLocal 该篇文章以<Redis实现短信验证码登录& ...

  6. java 判断请求为 ajax请求_Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求...

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 java 判断请求是不是ajax请求,Java判断是否为ajax请求 >>>>>> ...

  7. Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求

    Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,java 判断请求是不是ajax请求 Java过滤器处理Ajax请求,Java拦截器处理Ajax请求,拦截器Ajax请求 java 判断 ...

  8. java 金数据推送数据_基于JAVA的黄金数据接口调用代码实例

    代码描述:基于JAVA的黄金数据接口调用代码实例 接口地址:http://www.juhe.cn/docs/api/id/29 1.[代码][Java]代码 import java.io.Buffer ...

  9. 外汇汇率接口 java_基于java的货币汇率接口调用代码实例

    基于java的货币汇率接口调用代码实例 基于JAVA 的货币汇率接口调用代码实例 代码描述:基于JAVA 的货币汇率接口调用代码实例 代码平台:聚合数据 import java.io.Buffered ...

  10. 微信开发之——接口调用频率xianzh

    公众号调用接口并不是无限制的.为了防止公众号的程序错误而引发微信服务器负载异常,默认情况下,每个公众号调用接口都不能超过一定限制时,调用对应接口会收到如下错误返回码: {"errcode&q ...

最新文章

  1. BEGIN-1 A+B问题
  2. 驱动级模拟驱动级模拟:直接读写键盘的硬件端口!
  3. mysql inception web_基于Inception搭建MySQL SQL审核平台Yearing
  4. Express框架实现原理
  5. 如何在Debian 9上配置sources.list
  6. 对于原始轨迹的噪声过滤方法和曲率计算方法
  7. 在便宜、快速和可靠中三选二
  8. scrapy 爬取百度知道,多spider子一个项目中,使用一个pielines
  9. 谷歌离线地图二次开发源代码
  10. 敏捷开发scrum详解 敏捷项目管理流程
  11. Apache Tomcat AJP 文件包含漏洞复现(CVE-2020-10487)
  12. 【财经期刊FM-Radio|2021年03月13日】
  13. 在资源管理器中隐藏指定分区
  14. 显示控件——字符显示之艺术字
  15. IP防护等级解释说明
  16. 美国VPS服务器选择贴士
  17. 产业分析:二次元产业研究报告
  18. Office多版本共存,设置打开的版本
  19. Unity 骨骼动画 Anima2D
  20. 全网首发:彻底解决eclipse注释汉字英文大小不等的问题

热门文章

  1. python深度学习——手写字符识别
  2. kotlin官方文档中文翻译(二) 基础内容
  3. android 人脸识别边框_Android相机预览,指定区域显示预览框,在区域内出现人脸进行人脸识别,并抓拍人脸照片存在本地,CameraX,虹软人脸识别...
  4. python的设计模式
  5. python写鼠标宏_最全Pycharm教程(24)——Pycharm编辑器功能之宏定义
  6. java 1.6 jre 下载_jre1.6 64位官方下载
  7. 代码实现最简单的游戏————空中飞机
  8. STM32的新编译软件STM32CubeIDE
  9. Barrage 弹幕实现原理
  10. Linux无线网卡芯片RTL8188EUS驱动安装