av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁技術(shù)文章
文章詳情頁

Springboot使用redis實現(xiàn)接口Api限流的實例

瀏覽:18日期:2023-02-22 11:36:09
前言

Springboot使用redis實現(xiàn)接口Api限流的實例

該篇介紹的內(nèi)容如題,就是利用redis實現(xiàn)接口的限流( 某時間范圍內(nèi) 最大的訪問次數(shù) ) 。

正文

慣例,先看下我們的實戰(zhàn)目錄結(jié)構(gòu):

Springboot使用redis實現(xiàn)接口Api限流的實例

首先是pom.xml 核心依賴:

<!--用于redis數(shù)據(jù)庫連接--><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId></dependency><!--用于redis lettuce 連接池pool使用--><dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>

然后是application.yml里面的redis接入配置:

spring: redis: lettuce: pool:#連接池最大連接數(shù) 使用負值代表無限制 默認為8max-active: 10#最大空閑連接 默認8max-idle: 10#最小空閑連接 默認0min-idle: 1 host: 127.0.0.1 password: 123456 port: 6379 database: 0 timeout: 2000msserver: port: 8710

redis的配置類, RedisConfig.java:

ps:可以看到日期是18年的,因為這些redis的整合教程,在這個系列里面一共有快10篇,不了解的看客如果感興趣可以去看一看。

import com.fasterxml.jackson.annotation.JsonAutoDetect;import com.fasterxml.jackson.annotation.PropertyAccessor;import com.fasterxml.jackson.databind.ObjectMapper;import org.springframework.cache.CacheManager;import org.springframework.cache.annotation.EnableCaching;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.cache.RedisCacheConfiguration;import org.springframework.data.redis.cache.RedisCacheManager;import org.springframework.data.redis.connection.RedisConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;import org.springframework.data.redis.serializer.RedisSerializationContext;import org.springframework.data.redis.serializer.StringRedisSerializer; import static org.springframework.data.redis.cache.RedisCacheConfiguration.defaultCacheConfig; /** * @Author: JCccc * @CreateTime: 2018-09-11 * @Description: */@Configuration@EnableCachingpublic class RedisConfig { @Bean public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {RedisCacheConfiguration cacheConfiguration =defaultCacheConfig().disableCachingNullValues().serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new Jackson2JsonRedisSerializer(Object.class)));return RedisCacheManager.builder(connectionFactory).cacheDefaults(cacheConfiguration).build(); } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();redisTemplate.setConnectionFactory(factory);Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om = new ObjectMapper();om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);jackson2JsonRedisSerializer.setObjectMapper(om);//序列化設(shè)置 ,這樣為了存儲操作對象時正常顯示的數(shù)據(jù),也能正常存儲和獲取redisTemplate.setKeySerializer(new StringRedisSerializer());redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);redisTemplate.setHashKeySerializer(new StringRedisSerializer());redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);return redisTemplate; } @Bean public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {StringRedisTemplate stringRedisTemplate = new StringRedisTemplate();stringRedisTemplate.setConnectionFactory(factory);return stringRedisTemplate; }}

自定義注解:

import java.lang.annotation.*; /** * @Author JCccc * @Description * @Date 2021/7/23 11:46 */@Inherited@Documented@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface RequestLimit { /** * 時間內(nèi) 秒為單位 */ int second() default 10; /** * 允許訪問次數(shù) */ int maxCount() default 5; //默認效果 : 10秒內(nèi) 對于使用該注解的接口,只能總請求訪問數(shù) 不能大于 5次 }

接下來是攔截器 RequestLimitInterceptor.java:

攔截接口的方式 是通過 ip地址+接口url ,做時間內(nèi)的訪問計數(shù)

import com.elegant.testdemo.annotation.RequestLimit;import com.elegant.testdemo.utils.IpUtil;import com.fasterxml.jackson.databind.ObjectMapper;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.stereotype.Component;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.util.concurrent.TimeUnit; /** * @Author JCccc * @Description * @Date 2021/7/23 11:49 */ @Componentpublic class RequestLimitInterceptor implements HandlerInterceptor { private final Logger log = LoggerFactory.getLogger(this.getClass()); @Autowired private RedisTemplate<String, Object> redisTemplate; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {try { if (handler instanceof HandlerMethod) {HandlerMethod handlerMethod = (HandlerMethod) handler;// 獲取RequestLimit注解RequestLimit requestLimit = handlerMethod.getMethodAnnotation(RequestLimit.class);if (null==requestLimit) { return true;}//限制的時間范圍int seconds = requestLimit.second();//時間內(nèi)的 最大次數(shù)int maxCount = requestLimit.maxCount();String ipAddr = IpUtil.getIpAddr(request);// 存儲keyString key = ipAddr+':'+request.getContextPath() + ':' + request.getServletPath();// 已經(jīng)訪問的次數(shù)Integer count = (Integer) redisTemplate.opsForValue().get(key);log.info('檢測到目前ip對接口={}已經(jīng)訪問的次數(shù)', request.getServletPath() , count);if (null == count || -1 == count) { redisTemplate.opsForValue().set(key, 1, seconds, TimeUnit.SECONDS); return true;}if (count < maxCount) { redisTemplate.opsForValue().increment(key); return true;}log.warn('請求過于頻繁請稍后再試');returnData(response);return false; } return true;} catch (Exception e) { log.warn('請求過于頻繁請稍后再試'); e.printStackTrace();}return true; } public void returnData(HttpServletResponse response) throws IOException {response.setCharacterEncoding('UTF-8');response.setContentType('application/json; charset=utf-8');ObjectMapper objectMapper = new ObjectMapper();//這里傳提示語可以改成自己項目的返回數(shù)據(jù)封裝的類response.getWriter().println(objectMapper.writeValueAsString('請求過于頻繁請稍后再試'));return; } }

接下來是 攔截器的配置 WebConfig.java:

import com.elegant.testdemo.interceptor.RequestLimitInterceptor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; /** * @Author JCccc * @Description * @Date 2021/7/23 11:52 */ @Configurationpublic class WebConfig implements WebMvcConfigurer { @Autowired private RequestLimitInterceptor requestLimitInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(requestLimitInterceptor) //攔截所有請求路徑.addPathPatterns('/**')//再設(shè)置 放開哪些路徑.excludePathPatterns('/static/**','/auth/login'); } }

最后還有兩個工具類

IpUtil:

https://www.jb51.net/article/218249.htm

RedisUtil :

https://www.jb51.net/article/218246.htm

最后寫個測試接口

TestController.java

import com.elegant.testdemo.annotation.RequestLimit;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController; /** * @Author JCccc * @Description * @Date 2021/7/23 11:55 */@RestControllerpublic class TestController { @GetMapping('/test') @RequestLimit(maxCount = 3,second = 60) public String test() {return '你好,如果對你有幫助,請點贊加關(guān)注。'; } }

這個/test接口的注解,我們設(shè)置的是 60秒內(nèi) 最大訪問次數(shù)為 3次 (實際應用應該是根據(jù)具體接口做相關(guān)的次數(shù)限制。)

然后使用postman測試一下接口:

前面三次都是請求通過的:

Springboot使用redis實現(xiàn)接口Api限流的實例

Springboot使用redis實現(xiàn)接口Api限流的實例

第四次:

Springboot使用redis實現(xiàn)接口Api限流的實例

到此這篇關(guān)于Springboot使用redis實現(xiàn)接口Api限流的實例的文章就介紹到這了,更多相關(guān)Springboot redis接口Api限流內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 91精品国产乱码久久蜜臀 | 午夜视频免费在线观看 | 91久久网站 | 免费看大片bbbb欧美 | 久久精品综合网 | 波多野结衣先锋影音 | 精品欧美一区二区三区久久久 | 欧美视频在线播放 | 国产精品免费视频一区 | 免费久久99精品国产婷婷六月 | 欧美一级片在线观看 | 中文字幕av一区二区三区 | 美女一级a毛片免费观看97 | 99精品视频一区二区三区 | www.久久| 91.色| 亚洲欧美在线观看 | 久久久久久91| 在线视频一区二区 | 欧美激情一区二区三级高清视频 | 密室大逃脱第六季大神版在线观看 | 国产激情视频在线观看 | 在线91| 91精品国产高清一区二区三区 | 一级毛片视频 | 精品国产18久久久久久二百 | 99久久夜色精品国产亚洲96 | 国产精品美女久久久久久久久久久 | 欧美一区二区三区视频在线播放 | 中文字幕亚洲精品 | 不卡一区二区三区四区 | 欧美日韩国产一区二区三区 | 久久久精品综合 | 国产精品久久久久久久粉嫩 | 在线观看国产网站 | 国产伦精品一区二区三区精品视频 | 欧美一区二区三区在线观看 | 美国黄色毛片 | 欧美在线视频a | 理论片午午伦夜理片影院 | 欧美日韩高清一区 |