SpringBoot项目中接口防刷怎么实现

本篇内容主要讲解“SpringBoot项目中接口防刷怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot项目中接口防刷怎么实现”吧!

一、自定义注解

@H_502_4@import java.lang.annotation.Retention; import java.lang.annotation.Target; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.RetentionPolicy.RUNTIME; /**  * @author Yang  * @version 1.0  * @date 2021/2/22 10:28  */ @Retention(RUNTIME) @Target(METHOD) public @interface AccessLimit {     int seconds();     int maxCount();     boolean needLogin() default true; }

二、定义拦截

@H_502_4@import com.alibaba.fastjson.JSON; import com.mengxiangnongfu.payment.annotation.AccessLimit; import com.mengxiangnongfu.payment.commons.RedisUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; 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; /**  * @author Yang  * @version 1.0  * @date 2021/2/22 10:29  */ @Component public class FangshuaInterceptor extends handlerinterceptorAdapter {     @Autowired     private RedisUtil redisUtil;     @Override     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {         //判断请求是否属于方法的请求         if (handler instanceof HandlerMethod) {             HandlerMethod hm = (HandlerMethod) handler;             //获取方法中的注解,看是否有该注解             AccessLimit accessLimit = hm.getmethodAnnotation(AccessLimit.class);             if (accessLimit == null) {                 return true;             }             int seconds = accessLimit.seconds();             int maxCount = accessLimit.maxCount();             boolean login = accessLimit.needLogin();             String key = "1";             //如果需要登录             if (login) {                 //获取登录的session进行判断                 //.....                 key += "" + "1";  //这里假设用户是1,项目中是动态获取的userId             }             //从redis获取用户访问的次数             Integer count = (Integer) redisUtil.get(key);             if (count == null) {                 //第一次访问                 redisUtil.set(key, 1, seconds);             } else if (count < maxCount) {                 //加1                 redisUtil.incr(key, 1);             } else {                 //超出访问次数                 render(response, "请求过于频繁~请稍后再试~"); //这里的CodeMsg是一个返回参数                 return false;             }         }         return true;     }     private void render(HttpServletResponse response, String cm) throws Exception {         response.setContentType("application/json;charset=UTF-8");         OutputStream out = response.getoutputStream();         String str = JSON.toJSONString(cm);         out.write(str.getBytes("UTF-8"));         out.flush();         out.close();     } }

三、Redis工具类

@H_502_4@import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.core.Redistemplate; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; /**  * @author Yang  * @version 1.0  * @date 2020/11/29 17:06  */ @Component @Slf4j public class RedisUtil {     @Autowired     Redistemplate redistemplate;     // =============================common============================     /**      * 指定缓存失效时间      *      * @param key  键      * @param time 时间(秒)      * @return      */     public boolean expire(String key, long time) {         try {             if (time > 0) {                 redistemplate.expire(key, time, TimeUnit.SECONDS);             }             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 根据key 获取过期时间      *      * @param key 键 不能为null      * @return 时间(秒) 返回0代表为永久有效      */     public long getExpire(String key) {         return redistemplate.getExpire(key, TimeUnit.SECONDS);     }     /**      * 判断key是否存在      *      * @param key 键      * @return true 存在 false不存在      */     public boolean hasKey(String key) {         try {             return redistemplate.hasKey(key);         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 删除缓存      *      * @param key 可以传一个值 或多个      */     @SuppressWarnings("unchecked")     public void del(String... key) {         if (key != null && key.length > 0) {             if (key.length == 1) {                 redistemplate.delete(key[0]);             } else {                 redistemplate.delete(CollectionUtils.arrayToList(key));             }         }     }     // ============================String=============================     /**      * 普通缓存获取      *      * @param key 键      * @return 值      */     public Object get(String key) {         return key == null ? null : redistemplate.opsForValue().get(key);     }     /**      * 普通缓存放入      *      * @param key   键      * @param value 值      * @return true成功 false失败      */     public boolean set(String key, Object value) {         try {             redistemplate.opsForValue().set(key, value);             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 普通缓存放入并设置时间      *      * @param key   键      * @param value 值      * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期      * @return true成功 false 失败      */     public boolean set(String key, Object value, long time) {         try {             if (time > 0) {                 redistemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);             } else {                 set(key, value);             }             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 递增 适用场景: https://blog.csdn.net/y_y_y_k_k_k_k/article/details/79218254 高并发生成订单号,秒杀类的业务逻辑等。。      *      * @param key   键      * @param delta 要增加几(大于0)      * @return      */     public long incr(String key, long delta) {         if (delta < 0) {             throw new RuntimeException("递增因子必须大于0");         }         return redistemplate.opsForValue().increment(key, delta);     }     /**      * 递减      *      * @param key   键      * @param delta 要减少几(小于0)      * @return      */     public long decr(String key, long delta) {         if (delta < 0) {             throw new RuntimeException("递减因子必须大于0");         }         return redistemplate.opsForValue().increment(key, -delta);     }     // ================================Map=================================     /**      * HashGet      *      * @param key  键 不能为null      * @param item 项 不能为null      * @return 值      */     public Object hget(String key, String item) {         return redistemplate.opsForHash().get(key, item);     }     /**      * 获取hashKey对应的所有键值      *      * @param key 键      * @return 对应的多个键值      */     public Map<Object, Object> hmget(String key) {         return redistemplate.opsForHash().entries(key);     }     /**      * HashSet      *      * @param key 键      * @param map 对应多个键值      * @return true 成功 false 失败      */     public boolean hmset(String key, Map<String, Object> map) {         try {             redistemplate.opsForHash().putAll(key, map);             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * HashSet 并设置时间      *      * @param key  键      * @param map  对应多个键值      * @param time 时间(秒)      * @return true成功 false失败      */     public boolean hmset(String key, Map<String, Object> map, long time) {         try {             redistemplate.opsForHash().putAll(key, map);             if (time > 0) {                 expire(key, time);             }             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 向一张hash表中放入数据,如果不存在将创建      *      * @param key   键      * @param item  项      * @param value 值      * @return true 成功 false失败      */     public boolean hset(String key, String item, Object value) {         try {             redistemplate.opsForHash().put(key, item, value);             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 向一张hash表中放入数据,如果不存在将创建      *      * @param key   键      * @param item  项      * @param value 值      * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间      * @return true 成功 false失败      */     public boolean hset(String key, String item, Object value, long time) {         try {             redistemplate.opsForHash().put(key, item, value);             if (time > 0) {                 expire(key, time);             }             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 删除hash表中的值      *      * @param key  键 不能为null      * @param item 项 可以使多个 不能为null      */     public void hdel(String key, Object... item) {         redistemplate.opsForHash().delete(key, item);     }     /**      * 判断hash表中是否有该项的值      *      * @param key  键 不能为null      * @param item 项 不能为null      * @return true 存在 false不存在      */     public boolean hHasKey(String key, String item) {         return redistemplate.opsForHash().hasKey(key, item);     }     /**      * hash递增 如果不存在,就会创建一个 并把新增后的值返回      *      * @param key  键      * @param item 项      * @param by   要增加几(大于0)      * @return      */     public double hincr(String key, String item, double by) {         return redistemplate.opsForHash().increment(key, item, by);     }     /**      * hash递减      *      * @param key  键      * @param item 项      * @param by   要减少记(小于0)      * @return      */     public double hdecr(String key, String item, double by) {         return redistemplate.opsForHash().increment(key, item, -by);     }     // ============================set=============================     /**      * 根据key获取Set中的所有值      *      * @param key 键      * @return      */     public Set<Object> sGet(String key) {         try {             return redistemplate.opsForSet().members(key);         } catch (Exception e) {             log.error(key, e);             return null;         }     }     /**      * 根据value从一个set中查询,是否存在      *      * @param key   键      * @param value 值      * @return true 存在 false不存在      */     public boolean sHasKey(String key, Object value) {         try {             return redistemplate.opsForSet().isMember(key, value);         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 将数据放入set缓存      *      * @param key    键      * @param values 值 可以是多个      * @return 成功个数      */     public long sSet(String key, Object... values) {         try {             return redistemplate.opsForSet().add(key, values);         } catch (Exception e) {             log.error(key, e);             return 0;         }     }     /**      * 将set数据放入缓存      *      * @param key    键      * @param time   时间(秒)      * @param values 值 可以是多个      * @return 成功个数      */     public long sSetAndTime(String key, long time, Object... values) {         try {             Long count = redistemplate.opsForSet().add(key, values);             if (time > 0) {                 expire(key, time);             }             return count;         } catch (Exception e) {             log.error(key, e);             return 0;         }     }     /**      * 获取set缓存的长度      *      * @param key 键      * @return      */     public long sGetSetSize(String key) {         try {             return redistemplate.opsForSet().size(key);         } catch (Exception e) {             log.error(key, e);             return 0;         }     }     /**      * 移除值为value的      *      * @param key    键      * @param values 值 可以是多个      * @return 移除的个数      */     public long setRemove(String key, Object... values) {         try {             Long count = redistemplate.opsForSet().remove(key, values);             return count;         } catch (Exception e) {             log.error(key, e);             return 0;         }     }     // ============================zset=============================     /**      * 根据key获取Set中的所有值      *      * @param key 键      * @return      */     public Set<Object> zSGet(String key) {         try {             return redistemplate.opsForSet().members(key);         } catch (Exception e) {             log.error(key, e);             return null;         }     }     /**      * 根据value从一个set中查询,是否存在      *      * @param key   键      * @param value 值      * @return true 存在 false不存在      */     public boolean zSHasKey(String key, Object value) {         try {             return redistemplate.opsForSet().isMember(key, value);         } catch (Exception e) {             log.error(key, e);             return false;         }     }     public Boolean zSSet(String key, Object value, double score) {         try {             return redistemplate.opsForZSet().add(key, value, 2);         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 将set数据放入缓存      *      * @param key    键      * @param time   时间(秒)      * @param values 值 可以是多个      * @return 成功个数      */     public long zSSetAndTime(String key, long time, Object... values) {         try {             Long count = redistemplate.opsForSet().add(key, values);             if (time > 0) {                 expire(key, time);             }             return count;         } catch (Exception e) {             log.error(key, e);             return 0;         }     }     /**      * 获取set缓存的长度      *      * @param key 键      * @return      */     public long zSGetSetSize(String key) {         try {             return redistemplate.opsForSet().size(key);         } catch (Exception e) {             log.error(key, e);             return 0;         }     }     /**      * 移除值为value的      *      * @param key    键      * @param values 值 可以是多个      * @return 移除的个数      */     public long zSetRemove(String key, Object... values) {         try {             Long count = redistemplate.opsForSet().remove(key, values);             return count;         } catch (Exception e) {             log.error(key, e);             return 0;         }     }     // ===============================list=================================     /**      * 获取list缓存的内容      *      * @param key   键      * @param start 开始 0 是第一个元素      * @param end   结束 -1代表所有值      * @return      * @取出来的元素 总数 end-start+1      */     public List<Object> lGet(String key, long start, long end) {         try {             return redistemplate.opsForList().range(key, start, end);         } catch (Exception e) {             log.error(key, e);             return null;         }     }     /**      * 获取list缓存的长度      *      * @param key 键      * @return      */     public long lGetListSize(String key) {         try {             return redistemplate.opsForList().size(key);         } catch (Exception e) {             log.error(key, e);             return 0;         }     }     /**      * 通过索引 获取list中的值      *      * @param key   键      * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推      * @return      */     public Object lGetIndex(String key, long index) {         try {             return redistemplate.opsForList().index(key, index);         } catch (Exception e) {             log.error(key, e);             return null;         }     }     /**      * 将list放入缓存      *      * @param key   键      * @param value 值      * @return      */     public boolean lSet(String key, Object value) {         try {             redistemplate.opsForList().rightPush(key, value);             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 将list放入缓存      *      * @param key   键      * @param value 值      * @param time  时间(秒)      * @return      */     public boolean lSet(String key, Object value, long time) {         try {             redistemplate.opsForList().rightPush(key, value);             if (time > 0) {                 expire(key, time);             }             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 将list放入缓存      *      * @param key   键      * @param value 值      * @return      */     public boolean lSet(String key, List<Object> value) {         try {             redistemplate.opsForList().rightPushAll(key, value);             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 将list放入缓存      *      * @param key   键      * @param value 值      * @param time  时间(秒)      * @return      */     public boolean lSet(String key, List<Object> value, long time) {         try {             redistemplate.opsForList().rightPushAll(key, value);             if (time > 0) {                 expire(key, time);             }             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 根据索引修改list中的某条数据      *      * @param key   键      * @param index 索引      * @param value 值      * @return      */     public boolean lUpdateIndex(String key, long index, Object value) {         try {             redistemplate.opsForList().set(key, index, value);             return true;         } catch (Exception e) {             log.error(key, e);             return false;         }     }     /**      * 移除N个值为value      *      * @param key   键      * @param count 移除多少个      * @param value 值      * @return 移除的个数      */     public long lRemove(String key, long count, Object value) {         try {             Long remove = redistemplate.opsForList().remove(key, count, value);             return remove;         } catch (Exception e) {             log.error(key, e);             return 0;         }     } }

四、POM文件

@H_502_4@<groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-aop</artifactId>         </dependency>         <dependency>             <groupId>org.springframework.boot</groupId>             <artifactId>spring-boot-starter-data-redis</artifactId>         </dependency>

记得配置redis的连接

在需要拦截的地方加入注解即可@AccessLimit(seconds = 5, maxCount = 1, needLogin = false) seconds重置访问频率时间 maxCount 最多请求次数

到此,相信大家对“SpringBoot项目中接口防刷怎么实现”有了更深的了解,不妨来实际操作一番吧!这里是编程之家网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐