SpringBoot项目中接口防刷怎么实现
SpringBoot项目中接口防刷怎么实现
本篇内容主要讲解“SpringBoot项目中接口防刷怎么实现”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot项目中接口防刷怎么实现”吧!
一、自定义注解
importjava.lang.annotation.Retention;importjava.lang.annotation.Target;importstaticjava.lang.annotation.ElementType.METHOD;importstaticjava.lang.annotation.RetentionPolicy.RUNTIME;/***@authorYang*@version1.0*@date2021/2/2210:28*/@Retention(RUNTIME)@Target(METHOD)public@interfaceAccessLimit{intseconds();intmaxCount();booleanneedLogin()defaulttrue;}
二、定义拦截器
importcom.alibaba.fastjson.JSON;importcom.mengxiangnongfu.payment.annotation.AccessLimit;importcom.mengxiangnongfu.payment.commons.RedisUtil;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.context.annotation.Configuration;importorg.springframework.stereotype.Component;importorg.springframework.web.method.HandlerMethod;importorg.springframework.web.servlet.handler.HandlerInterceptorAdapter;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importjava.io.OutputStream;/***@authorYang*@version1.0*@date2021/2/2210:29*/@ComponentpublicclassFangshuaInterceptorextendsHandlerInterceptorAdapter{@AutowiredprivateRedisUtilredisUtil;@OverridepublicbooleanpreHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler)throwsException{//判断请求是否属于方法的请求if(handlerinstanceofHandlerMethod){HandlerMethodhm=(HandlerMethod)handler;//获取方法中的注解,看是否有该注解AccessLimitaccessLimit=hm.getMethodAnnotation(AccessLimit.class);if(accessLimit==null){returntrue;}intseconds=accessLimit.seconds();intmaxCount=accessLimit.maxCount();booleanlogin=accessLimit.needLogin();Stringkey="1";//如果需要登录if(login){//获取登录的session进行判断//.....key+=""+"1";//这里假设用户是1,项目中是动态获取的userId}//从redis中获取用户访问的次数Integercount=(Integer)redisUtil.get(key);if(count==null){//第一次访问redisUtil.set(key,1,seconds);}elseif(count<maxCount){//加1redisUtil.incr(key,1);}else{//超出访问次数render(response,"请求过于频繁~请稍后再试~");//这里的CodeMsg是一个返回参数returnfalse;}}returntrue;}privatevoidrender(HttpServletResponseresponse,Stringcm)throwsException{response.setContentType("application/json;charset=UTF-8");OutputStreamout=response.getOutputStream();Stringstr=JSON.toJSONString(cm);out.write(str.getBytes("UTF-8"));out.flush();out.close();}}
三、Redis工具类
importlombok.extern.slf4j.Slf4j;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.stereotype.Component;importorg.springframework.util.CollectionUtils;importjava.util.List;importjava.util.Map;importjava.util.Set;importjava.util.concurrent.TimeUnit;/***@authorYang*@version1.0*@date2020/11/2917:06*/@Component@Slf4jpublicclassRedisUtil{@AutowiredRedisTemplateredisTemplate;//=============================common============================/***指定缓存失效时间**@paramkey键*@paramtime时间(秒)*@return*/publicbooleanexpire(Stringkey,longtime){try{if(time>0){redisTemplate.expire(key,time,TimeUnit.SECONDS);}returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***根据key获取过期时间**@paramkey键不能为null*@return时间(秒)返回0代表为永久有效*/publiclonggetExpire(Stringkey){returnredisTemplate.getExpire(key,TimeUnit.SECONDS);}/***判断key是否存在**@paramkey键*@returntrue存在false不存在*/publicbooleanhasKey(Stringkey){try{returnredisTemplate.hasKey(key);}catch(Exceptione){log.error(key,e);returnfalse;}}/***删除缓存**@paramkey可以传一个值或多个*/@SuppressWarnings("unchecked")publicvoiddel(String...key){if(key!=null&&key.length>0){if(key.length==1){redisTemplate.delete(key[0]);}else{redisTemplate.delete(CollectionUtils.arrayToList(key));}}}//============================String=============================/***普通缓存获取**@paramkey键*@return值*/publicObjectget(Stringkey){returnkey==null?null:redisTemplate.opsForValue().get(key);}/***普通缓存放入**@paramkey键*@paramvalue值*@returntrue成功false失败*/publicbooleanset(Stringkey,Objectvalue){try{redisTemplate.opsForValue().set(key,value);returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***普通缓存放入并设置时间**@paramkey键*@paramvalue值*@paramtime时间(秒)time要大于0如果time小于等于0将设置无限期*@returntrue成功false失败*/publicbooleanset(Stringkey,Objectvalue,longtime){try{if(time>0){redisTemplate.opsForValue().set(key,value,time,TimeUnit.SECONDS);}else{set(key,value);}returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***递增适用场景:https://blog.csdn.net/y_y_y_k_k_k_k/article/details/79218254高并发生成订单号,秒杀类的业务逻辑等。。**@paramkey键*@paramdelta要增加几(大于0)*@return*/publiclongincr(Stringkey,longdelta){if(delta<0){thrownewRuntimeException("递增因子必须大于0");}returnredisTemplate.opsForValue().increment(key,delta);}/***递减**@paramkey键*@paramdelta要减少几(小于0)*@return*/publiclongdecr(Stringkey,longdelta){if(delta<0){thrownewRuntimeException("递减因子必须大于0");}returnredisTemplate.opsForValue().increment(key,-delta);}//================================Map=================================/***HashGet**@paramkey键不能为null*@paramitem项不能为null*@return值*/publicObjecthget(Stringkey,Stringitem){returnredisTemplate.opsForHash().get(key,item);}/***获取hashKey对应的所有键值**@paramkey键*@return对应的多个键值*/publicMap<Object,Object>hmget(Stringkey){returnredisTemplate.opsForHash().entries(key);}/***HashSet**@paramkey键*@parammap对应多个键值*@returntrue成功false失败*/publicbooleanhmset(Stringkey,Map<String,Object>map){try{redisTemplate.opsForHash().putAll(key,map);returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***HashSet并设置时间**@paramkey键*@parammap对应多个键值*@paramtime时间(秒)*@returntrue成功false失败*/publicbooleanhmset(Stringkey,Map<String,Object>map,longtime){try{redisTemplate.opsForHash().putAll(key,map);if(time>0){expire(key,time);}returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***向一张hash表中放入数据,如果不存在将创建**@paramkey键*@paramitem项*@paramvalue值*@returntrue成功false失败*/publicbooleanhset(Stringkey,Stringitem,Objectvalue){try{redisTemplate.opsForHash().put(key,item,value);returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***向一张hash表中放入数据,如果不存在将创建**@paramkey键*@paramitem项*@paramvalue值*@paramtime时间(秒)注意:如果已存在的hash表有时间,这里将会替换原有的时间*@returntrue成功false失败*/publicbooleanhset(Stringkey,Stringitem,Objectvalue,longtime){try{redisTemplate.opsForHash().put(key,item,value);if(time>0){expire(key,time);}returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***删除hash表中的值**@paramkey键不能为null*@paramitem项可以使多个不能为null*/publicvoidhdel(Stringkey,Object...item){redisTemplate.opsForHash().delete(key,item);}/***判断hash表中是否有该项的值**@paramkey键不能为null*@paramitem项不能为null*@returntrue存在false不存在*/publicbooleanhHasKey(Stringkey,Stringitem){returnredisTemplate.opsForHash().hasKey(key,item);}/***hash递增如果不存在,就会创建一个并把新增后的值返回**@paramkey键*@paramitem项*@paramby要增加几(大于0)*@return*/publicdoublehincr(Stringkey,Stringitem,doubleby){returnredisTemplate.opsForHash().increment(key,item,by);}/***hash递减**@paramkey键*@paramitem项*@paramby要减少记(小于0)*@return*/publicdoublehdecr(Stringkey,Stringitem,doubleby){returnredisTemplate.opsForHash().increment(key,item,-by);}//============================set=============================/***根据key获取Set中的所有值**@paramkey键*@return*/publicSet<Object>sGet(Stringkey){try{returnredisTemplate.opsForSet().members(key);}catch(Exceptione){log.error(key,e);returnnull;}}/***根据value从一个set中查询,是否存在**@paramkey键*@paramvalue值*@returntrue存在false不存在*/publicbooleansHasKey(Stringkey,Objectvalue){try{returnredisTemplate.opsForSet().isMember(key,value);}catch(Exceptione){log.error(key,e);returnfalse;}}/***将数据放入set缓存**@paramkey键*@paramvalues值可以是多个*@return成功个数*/publiclongsSet(Stringkey,Object...values){try{returnredisTemplate.opsForSet().add(key,values);}catch(Exceptione){log.error(key,e);return0;}}/***将set数据放入缓存**@paramkey键*@paramtime时间(秒)*@paramvalues值可以是多个*@return成功个数*/publiclongsSetAndTime(Stringkey,longtime,Object...values){try{Longcount=redisTemplate.opsForSet().add(key,values);if(time>0){expire(key,time);}returncount;}catch(Exceptione){log.error(key,e);return0;}}/***获取set缓存的长度**@paramkey键*@return*/publiclongsGetSetSize(Stringkey){try{returnredisTemplate.opsForSet().size(key);}catch(Exceptione){log.error(key,e);return0;}}/***移除值为value的**@paramkey键*@paramvalues值可以是多个*@return移除的个数*/publiclongsetRemove(Stringkey,Object...values){try{Longcount=redisTemplate.opsForSet().remove(key,values);returncount;}catch(Exceptione){log.error(key,e);return0;}}//============================zset=============================/***根据key获取Set中的所有值**@paramkey键*@return*/publicSet<Object>zSGet(Stringkey){try{returnredisTemplate.opsForSet().members(key);}catch(Exceptione){log.error(key,e);returnnull;}}/***根据value从一个set中查询,是否存在**@paramkey键*@paramvalue值*@returntrue存在false不存在*/publicbooleanzSHasKey(Stringkey,Objectvalue){try{returnredisTemplate.opsForSet().isMember(key,value);}catch(Exceptione){log.error(key,e);returnfalse;}}publicBooleanzSSet(Stringkey,Objectvalue,doublescore){try{returnredisTemplate.opsForZSet().add(key,value,2);}catch(Exceptione){log.error(key,e);returnfalse;}}/***将set数据放入缓存**@paramkey键*@paramtime时间(秒)*@paramvalues值可以是多个*@return成功个数*/publiclongzSSetAndTime(Stringkey,longtime,Object...values){try{Longcount=redisTemplate.opsForSet().add(key,values);if(time>0){expire(key,time);}returncount;}catch(Exceptione){log.error(key,e);return0;}}/***获取set缓存的长度**@paramkey键*@return*/publiclongzSGetSetSize(Stringkey){try{returnredisTemplate.opsForSet().size(key);}catch(Exceptione){log.error(key,e);return0;}}/***移除值为value的**@paramkey键*@paramvalues值可以是多个*@return移除的个数*/publiclongzSetRemove(Stringkey,Object...values){try{Longcount=redisTemplate.opsForSet().remove(key,values);returncount;}catch(Exceptione){log.error(key,e);return0;}}//===============================list=================================/***获取list缓存的内容**@paramkey键*@paramstart开始0是第一个元素*@paramend结束-1代表所有值*@return*@取出来的元素总数end-start+1*/publicList<Object>lGet(Stringkey,longstart,longend){try{returnredisTemplate.opsForList().range(key,start,end);}catch(Exceptione){log.error(key,e);returnnull;}}/***获取list缓存的长度**@paramkey键*@return*/publiclonglGetListSize(Stringkey){try{returnredisTemplate.opsForList().size(key);}catch(Exceptione){log.error(key,e);return0;}}/***通过索引获取list中的值**@paramkey键*@paramindex索引index>=0时,0表头,1第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推*@return*/publicObjectlGetIndex(Stringkey,longindex){try{returnredisTemplate.opsForList().index(key,index);}catch(Exceptione){log.error(key,e);returnnull;}}/***将list放入缓存**@paramkey键*@paramvalue值*@return*/publicbooleanlSet(Stringkey,Objectvalue){try{redisTemplate.opsForList().rightPush(key,value);returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***将list放入缓存**@paramkey键*@paramvalue值*@paramtime时间(秒)*@return*/publicbooleanlSet(Stringkey,Objectvalue,longtime){try{redisTemplate.opsForList().rightPush(key,value);if(time>0){expire(key,time);}returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***将list放入缓存**@paramkey键*@paramvalue值*@return*/publicbooleanlSet(Stringkey,List<Object>value){try{redisTemplate.opsForList().rightPushAll(key,value);returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***将list放入缓存**@paramkey键*@paramvalue值*@paramtime时间(秒)*@return*/publicbooleanlSet(Stringkey,List<Object>value,longtime){try{redisTemplate.opsForList().rightPushAll(key,value);if(time>0){expire(key,time);}returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***根据索引修改list中的某条数据**@paramkey键*@paramindex索引*@paramvalue值*@return*/publicbooleanlUpdateIndex(Stringkey,longindex,Objectvalue){try{redisTemplate.opsForList().set(key,index,value);returntrue;}catch(Exceptione){log.error(key,e);returnfalse;}}/***移除N个值为value**@paramkey键*@paramcount移除多少个*@paramvalue值*@return移除的个数*/publiclonglRemove(Stringkey,longcount,Objectvalue){try{Longremove=redisTemplate.opsForList().remove(key,count,value);returnremove;}catch(Exceptione){log.error(key,e);return0;}}}
四、POM文件
<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项目中接口防刷怎么实现”有了更深的了解,不妨来实际操作一番吧!这里是恰卡编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
推荐阅读
-
springboot实现基于aop的切面日志
本文实例为大家分享了springboot实现基于aop的切面日志的具体代码,供大家参考,具体内容如下通过aop的切面方式实现日志...
-
SpringBoot定时任务功能怎么实现
-
SpringBoot中的@Import注解怎么使用
-
SpringBoot整合Lombok及常见问题怎么解决
-
springboot图片验证码功能模块怎么实现
-
Springboot+SpringSecurity怎么实现图片验证码登录
-
SpringBoot注解的知识点有哪些
SpringBoot注解的知识点有哪些这篇“SpringBoot注...
-
SpringBoot2.x中management.security.enabled=false无效怎么解决
-
springboot怎么禁用某项健康检查
springboot怎么禁用某项健康检查今天小编给大家分享一下sp...
-
SpringBoot2怎么自定义端点