springboot接口限制访问次数

对接口访问次数的限制 是从java版web项目公众号中看到 于是百度结合自己现有项目写了一下

首先需要定义一个注解

    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
     
    /**
     * @Auther: lirui
     * @Date: 2020/11/1 0:12
     * @Description: 接口防刷注解类
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface AccessLimit {
     
        int seconds();
        int maxcount();
        boolean needLogin() default true;
    }

接口防刷拦截器

    import com.bigdata.bigdata.annotations.AccessLimit;
    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.handler.HandlerInterceptorAdapter;
     
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.OutputStream;
     
    /**
     * @Auther: lirui
     * @Date: 2020/11/1 0:12
     * @Description: 接口防刷拦截器
     */
    @Component
    public class FangshuaInterceptor extends HandlerInterceptorAdapter {
     
        @Autowired
        private RedisTemplate redisTemplate;
     
     
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            //判断请求是否属于方法的请求
            if(handler instanceof HandlerMethod){
                HandlerMethod handlerMethod=(HandlerMethod) handler;
     
                //获取方法中的注解,看是否有该注解
                AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class);
                if(accessLimit==null){
                    return true;
                }
                int seconds = accessLimit.seconds();
                int maxcount = accessLimit.maxcount();
                boolean login = accessLimit.needLogin();
                String key = request.getRequestURI();
                //如果需要登录
                if(login){
                    //获取登录的session进行判断
                    //.......
                    key+=""+"1"; //用户id userId
                }
     
                //从redis中获取用户访问的次数
    //            AccessKey ak = AccessKey.withExpire(seconds);
                Integer count= (Integer)redisTemplate.opsForValue().get(key);
                if(count==null){
                    //第一次访问
                    redisTemplate.opsForValue().set(key,1);
                }else if(count<maxcount){
                    //加1
                    redisTemplate.opsForValue().set(key,(Integer)redisTemplate.opsForValue().get(key)+1);
                }else{
                    //超出访问次数
                    render(response,key+"接口请求次数过多!");
                    return false;
                }
            }
            return true;
        }
     
        private void render(HttpServletResponse response, String message)throws Exception {
            response.setContentType("application/json;charset=UTF-8");
            OutputStream out = response.getOutputStream();
            out.write(message.getBytes("UTF-8"));
            out.flush();
            out.close();
        }
    }
     

将拦截器注册到spring容器中

    package com.bigdata.bigdata.config;
     
    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.WebMvcConfigurerAdapter;
     
    /**
     * @Auther: lirui
     * @Date: 2020/11/1 0:12
     * @Description: 将防刷拦截器注册 到springcloud容器中
     */
     
    @Configuration
    public class WebConfig  extends WebMvcConfigurerAdapter {
     
        @Autowired
        private FangshuaInterceptor interceptor;
     
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(interceptor);
        }
    }

controller接口编写

    import com.bigdata.bigdata.annotations.AccessLimit;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
     
    /**
     * @Auther: lirui
     * @Date: 2020/11/1 0:12
     * @Description: 防刷接口测试
     */
    @RestController
    @RequestMapping("/fangshua")
    public class FangshuaController {
     
        @AccessLimit(seconds = 5, maxcount = 5, needLogin = false)
        @RequestMapping("/test")
        public String test() {
            return "请求成功";
        }
     
    }