Springboot 는 redis 를 사용 하여 인터페이스 Api 의 흐름 을 제한 하 는 인 스 턴 스 를 실현 합 니 다.

머리말

이 소개 내용 은 제목 과 같이 redis 를 이용 하여 인터페이스의 제한 흐름 을 실현 하 는 것 이다( 모 시간 범위 내 최대 접근 횟수) 。
본문 
관례 는 먼저 우리 의 실전 목록 구 조 를 살 펴 보 자.

우선 pom.xml 핵심 의존:

        <!--  redis     -->
        <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:
        #                      8
        max-active: 10
        #         8
        max-idle: 10
        #         0
        min-idle: 1
    host: 127.0.0.1
    password: 123456
    port: 6379
    database: 0
    timeout: 2000ms
server:
  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
@EnableCaching
public 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);
        //      ,                  ,         
        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 {
 
    /**
     *          
     */
    int second() default 10; 
 
    /**
     *        
     */
    int maxCount() default 5;
 
 
    //     : 10             ,              5 
 
}
다음은 차단기 RequestLimit Interceptor.java:
인 터 페 이 스 를 차단 하 는 방식 은 ip 주소+인터페이스 url 을 통 해 시간 내 접근 수 를 계산 하 는 것 입 니 다.

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
 */
 
@Component
public 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();
                //         
                int maxCount = requestLimit.maxCount();
                String ipAddr = IpUtil.getIpAddr(request);
                //   key
                String key =  ipAddr+":"+request.getContextPath() + ":" + request.getServletPath();
                //        
                Integer count = (Integer) redisTemplate.opsForValue().get(key);
                log.info("     ip   ={}       ", 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();
        //                       
        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
 */
 
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private RequestLimitInterceptor requestLimitInterceptor;
 
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(requestLimitInterceptor)
 
                //        
                .addPathPatterns("/**")
                //          
                .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
 */
@RestController
public class TestController {
 
    @GetMapping("/test")
    @RequestLimit(maxCount = 3,second = 60)
    public String test() {
        return "  ,       ,      。";
    } 
}
이/test 인터페이스의 주 해 는 60 초 동안 최대 방문 횟수 를 3 회 로 설정 합 니 다.(실제 응용 은 구체 적 인 인터페이스 에 따라 관련 횟수 를 제한 해 야 합 니 다.)
그리고 postman 을 사용 하여 인 터 페 이 스 를 테스트 합 니 다:
앞의 세 번 은 모두 통 과 를 요청 한 것 이다.
 

 네 번 째:

Springboot 에서 redis 를 사용 하여 인터페이스 Api 의 흐름 을 제한 하 는 인 스 턴 스 를 실현 하 는 이 글 은 여기까지 소개 합 니 다.더 많은 Springboot redis 인터페이스 Api 의 흐름 제한 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기