栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

redis做限流量

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

redis做限流量

定义一个注解标明需要使用限流的接口
import java.lang.annotation.*;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;



@Retention(RUNTIME)
@Target(METHOD)

public @interface AccessLimit {
    int seconds();
    int maxCount();
}
配置拦截器
import com.alibaba.fastjson.JSONObject;
import com.vip.file.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.HashMap;

@Component
public class WebSecurityConfig implements HandlerInterceptor {
    @Autowired
    private RedisService redisService;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        //如果请求输入方法
        if (handler instanceof HandlerMethod) {
            HandlerMethod hm = (HandlerMethod) handler;
            //获取方法中的注解,看是否有该注解
            AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
            if (accessLimit != null) {
                long seconds = accessLimit.seconds();
                int maxCount = accessLimit.maxCount();
//关于key的生成规则可以自己定义 本项目需求是对每个方法都加上限流功能,如果你只是针对ip地址限流,那么key只需要只用ip就好
//                String key =     SystemUtil.getClientIp(httpServletRequest)+hm.getMethod().getName();
                String key = "192.168.2.149";

                HashMap hashMap = new HashMap<>();
                //从redis中获取用户访问的次数
                try {
                    long q = redisService.incr(key, seconds);//此操作代表获取该key对应的值自增1后的结果
                    System.out.println("从redis中获取用户访问的次数q: "+q);
                    if (q > maxCount) {
                        //加1
//                        render(httpServletResponse, new ResponseMsg(0, "请求过于频繁,请稍候再试", null)); //这里的CodeMsg是一个返回参数
                        render(httpServletResponse, "请求过于频繁,请稍候再试"); //这里的CodeMsg是一个返回参数
                        System.out.println("请求过于频繁,请稍候再试");
                        return false;
                    }
                    return true;
                } catch (RedisConnectionFailureException e) {
//                    logger.info("redis错误" + e.getMessage().toString());
                    System.out.println("redis错误" + e.getMessage().toString());
                    return true;
                }
            }

        }


        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }

    private void render(HttpServletResponse response, String cm) throws Exception {
        response.setContentType("application/json;charset=UTF-8");
        OutputStream out = response.getOutputStream();
        HashMap hashMap = new HashMap<>();
        hashMap.put("message", "请求过于频繁,请稍候再试");
        JSonObject data = new JSonObject(hashMap);
        out.write(data.toJSonString().getBytes("UTF-8"));
        out.flush();
        out.close();
    }
}
注册拦截器,设置拦截的接口路径 /pdf/test1
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private WebSecurityConfig webSecurityConfig;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(webSecurityConfig).addPathPatterns("/pdf/test1").excludePathPatterns("/static
    boolean set(String key, String value);

    
    String get(String key);

    
    boolean expire(String key, long expire);

    
    boolean remove(String key);

    
    Long incr(String key,long time);
}
import com.vip.file.service.RedisService;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

@Service("redisService")
public class RedisServiceImpl implements RedisService {


    @Resource
    private RedisTemplate redisTemplate;


    @Override
    public boolean set(final String key, final String value) {
        boolean result = redisTemplate.execute(new RedisCallback() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer serializer = redisTemplate.getStringSerializer();
                connection.set(serializer.serialize(key), serializer.serialize(value));
                return true;
            }
        });
        return result;
    }

    @Override
    public String get(final String key) {
        String result = redisTemplate.execute(new RedisCallback() {
            @Override
            public String doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer serializer = redisTemplate.getStringSerializer();
                byte[] value = connection.get(serializer.serialize(key));
                return serializer.deserialize(value);
            }
        });
        return result;
    }

    @Override
    public boolean expire(final String key, long expire) {
        return redisTemplate.expire(key, expire, TimeUnit.SECONDS);
    }

    @Override
    public boolean remove(final String key) {
        boolean result = redisTemplate.execute(new RedisCallback() {
            @Override
            public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                RedisSerializer serializer = redisTemplate.getStringSerializer();
                connection.del(key.getBytes());
                return true;
            }
        });
        return result;
    }
    @Override
    public Long incr(String key,long time){
        long count = redisTemplate.opsForValue().increment(key, 1);
        if (count == 1) {
            //设置有效期一分钟
            set(key,"1");
            redisTemplate.expire(key, time, TimeUnit.SECONDS);
        }
        return count;
    }
}

 接口

    @AccessLimit(seconds = 5,maxCount = 5)
    @GetMapping("/test1")
    public void test2(){
        System.out.println("/test1");
    }

并发100请求,只限流5个请求

 

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/785467.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号