当前位置: 首页 > news >正文

济南网站建设认可搜点网络上海科技网站建设

济南网站建设认可搜点网络,上海科技网站建设,凡客官网免费制作小程序,云制造网站目录 介绍 限流的思路 代码示例 必需pom依赖 自定义注解 redis工具类 redis配置类 主拦截器 注册拦截器 介绍 限流的需求出现在许多常见的场景中#xff1a; 秒杀活动#xff0c;有人使用软件恶意刷单抢货#xff0c;需要限流防止机器参与活动 某 api 被各式各样…目录 介绍 限流的思路 代码示例 必需pom依赖 自定义注解 redis工具类 redis配置类 主拦截器 注册拦截器 介绍 限流的需求出现在许多常见的场景中 秒杀活动有人使用软件恶意刷单抢货需要限流防止机器参与活动 某 api 被各式各样系统广泛调用严重消耗网络、内存等资源需要合理限流 淘宝获取 ip 所在城市接口、微信公众号识别微信用户等开发接口免费提供给用户时需要限流更 具有实时性和准确性的接口需要付费。 限流的思路 通过 ip:api 路径 的作为 key 访问次数为 value 的方式对某一用户的某一请求进行唯一标识 每次访问的时候判断 key 是否存在是否 count 超过了限制的访问次数 若访问超出限制则应 response 返回 msg: 请求过于频繁 给前端予以展示 代码示例 准备一个springboot项目 必需pom依赖 dependencies !-- web开发场景启动器--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependency !-- redis--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId/dependencydependencygroupIdredis.clients/groupIdartifactIdjedis/artifactIdversion2.9.3/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependencies 自定义注解 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;//运行时执行 Retention(RetentionPolicy.RUNTIME) //指定注解的适用目标 表示该注解适用于方法上。 Target(ElementType.METHOD) public interface AccessLimit {/*** 限制时长 秒*/int seconds();/*** 最大访问次数*/int maxCount();/*** 是否需要登录*/boolean needLogin() default true; } redis工具类 import org.springframework.beans.factory.annotation.Autowired; 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.Component; import org.springframework.util.CollectionUtils; import redis.clients.jedis.Protocol; import redis.clients.util.SafeEncoder;import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit;Component public class RedisUtil {Autowiredprivate RedisTemplateString, Object 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) {e.printStackTrace();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) {e.printStackTrace();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((CollectionString) CollectionUtils.arrayToList(key));}}}/*** 删除缓存* param keys 可以传一个值 或多个*/public void del(CollectionString keys) {if (CollectionUtils.isEmpty(keys)) {redisTemplate.delete(keys);}}// 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) {e.printStackTrace();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) {e.printStackTrace();return false;}}/*** 递增* 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 MapObject, Object hmget(String key) {return redisTemplate.opsForHash().entries(key);}/*** HashSet* param key 键* param map 对应多个键值* return true 成功 false 失败*/public boolean hmset(String key, MapString, Object map) {try {redisTemplate.opsForHash().putAll(key, map);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** HashSet 并设置时间* param key 键* param map 对应多个键值* param time 时间(秒)* return true成功 false失败*/public boolean hmset(String key, MapString, Object map, long time) {try {redisTemplate.opsForHash().putAll(key, map);if (time 0) {expire(key, time);}return true;} catch (Exception e) {e.printStackTrace();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) {e.printStackTrace();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) {e.printStackTrace();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 items 项 可以使多个 不能为null*/public void hdel(String key, Collection items) {redisTemplate.opsForHash().delete(key, items.toArray());}/*** 判断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 delta 要增加几(大于0)* return*/public double hincr(String key, String item, double delta) {if (delta 0) {throw new RuntimeException(递增因子必须大于0);}return redisTemplate.opsForHash().increment(key, item, delta);}/*** hash递减* param key 键* param item 项* param delta 要减少记(小于0)* return*/public double hdecr(String key, String item, double delta) {if (delta 0) {throw new RuntimeException(递减因子必须大于0);}return redisTemplate.opsForHash().increment(key, item, -delta);}// set/*** 根据key获取Set中的所有值* param key 键* return*/public SetObject sGet(String key) {try {return redisTemplate.opsForSet().members(key);} catch (Exception e) {e.printStackTrace();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) {e.printStackTrace();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) {e.printStackTrace();return 0;}}/*** 将数据放入set缓存* param key 键* param values 值 可以是多个* return 成功个数*/public long sSet(String key, Collection values) {try {return redisTemplate.opsForSet().add(key, values.toArray());} catch (Exception e) {e.printStackTrace();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) {e.printStackTrace();return 0;}}/*** 获取set缓存的长度* param key 键* return*/public long sGetSetSize(String key) {try {return redisTemplate.opsForSet().size(key);} catch (Exception e) {e.printStackTrace();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) {e.printStackTrace();return 0;}}// list/*** 获取list缓存的内容* param key 键* param start 开始* param end 结束 0 到 -1代表所有值* return*/public ListObject lGet(String key, long start, long end) {try {return redisTemplate.opsForList().range(key, start, end);} catch (Exception e) {e.printStackTrace();return null;}}/*** 获取list缓存的长度* param key 键* return*/public long lGetListSize(String key) {try {return redisTemplate.opsForList().size(key);} catch (Exception e) {e.printStackTrace();return 0;}}/*** 通过索引 获取list中的值* param key 键* param index 索引 index0时 0 表头1 第二个元素依次类推index0时-1表尾-2倒数第二个元素依次类推* return*/public Object lGetIndex(String key, long index) {try {return redisTemplate.opsForList().index(key, index);} catch (Exception e) {e.printStackTrace();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) {e.printStackTrace();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) {e.printStackTrace();return false;}}/*** 将list放入缓存* param key 键* param value 值* return*/public boolean lSet(String key, ListObject value) {try {redisTemplate.opsForList().rightPushAll(key, value);return true;} catch (Exception e) {e.printStackTrace();return false;}}/*** 将list放入缓存** param key 键* param value 值* param time 时间(秒)* return*/public boolean lSet(String key, ListObject value, long time) {try {redisTemplate.opsForList().rightPushAll(key, value);if (time 0)expire(key, time);return true;} catch (Exception e) {e.printStackTrace();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) {e.printStackTrace();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) {e.printStackTrace();return 0;}}/*** RedisTemplate 实现 setnx exptime (扩展 redisTemplate.setIfAbsent)** 之前用 redisTemplate 实现setnx exptime 时 是分两步的* 1. redisTemplate.setIfAbsent* 2. redisTemplate.expire* 这样的不是原子性的 可能在第一步与第二步之间 重新发布了或者服务器重启了* 这个key就永远不会消失了 可以采用以下的方法** param key* param value* param exptime* return*/public boolean setIfAbsent(final String key, final Serializable value, final long exptime) {Boolean b (Boolean) redisTemplate.execute(new RedisCallbackBoolean() {Overridepublic Boolean doInRedis(RedisConnection connection) throws DataAccessException {RedisSerializer valueSerializer redisTemplate.getValueSerializer();RedisSerializer keySerializer redisTemplate.getKeySerializer();Object obj connection.execute(set, keySerializer.serialize(key),valueSerializer.serialize(value),SafeEncoder.encode(NX),//EX 秒PX 毫秒SafeEncoder.encode(EX),Protocol.toByteArray(exptime));return obj ! null;}});return b;} }redis配置类 import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.*; import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;Configuration EnableCaching public class RedisConfig extends CachingConfigurerSupport {/*** retemplate相关配置* param factory* return*/Beanpublic RedisTemplateString, Object redisTemplate(RedisConnectionFactory factory) {RedisTemplateString, Object template new RedisTemplate();// 配置连接工厂template.setConnectionFactory(factory);//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值默认使用JDK的序列化方式Jackson2JsonRedisSerializer jacksonSeial new Jackson2JsonRedisSerializer(Object.class);ObjectMapper om new ObjectMapper();// 指定要序列化的域field,get和set,以及修饰符范围ANY是都有包括private和publicom.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);// 指定序列化输入的类型类必须是非final修饰的final修饰的类比如String,Integer等会跑出异常// om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); // jacksonSeial.setObjectMapper(om);// 值采用json序列化template.setValueSerializer(jacksonSeial);//使用StringRedisSerializer来序列化和反序列化redis的key值template.setKeySerializer(new StringRedisSerializer());// 设置hash key 和value序列化模式template.setHashKeySerializer(new StringRedisSerializer());template.setHashValueSerializer(jacksonSeial);template.afterPropertiesSet();return template;}/*** 对hash类型的数据操作** param redisTemplate* return*/Beanpublic HashOperationsString, String, Object hashOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForHash();}/*** 对redis字符串类型数据操作** param redisTemplate* return*/Beanpublic ValueOperationsString, Object valueOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForValue();}/*** 对链表类型的数据操作** param redisTemplate* return*/Beanpublic ListOperationsString, Object listOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForList();}/*** 对无序集合类型的数据操作** param redisTemplate* return*/Beanpublic SetOperationsString, Object setOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForSet();}/*** 对有序集合类型的数据操作** param redisTemplate* return*/Beanpublic ZSetOperationsString, Object zSetOperations(RedisTemplateString, Object redisTemplate) {return redisTemplate.opsForZSet();} } 主拦截器 import com.example.demo.service.AccessLimit; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor;Component public class AccessLimitInterceptor implements HandlerInterceptor {Resourceprivate RedisUtil redisUtil;Overridepublic 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(accessLimitnull){return true;}//时间int seconds accessLimit.seconds();//最大次数int maxCount accessLimit.maxCount();boolean needLogin accessLimit.needLogin();if(needLogin){//判断是否登录}//获取访问ip和路径String iprequest.getRemoteAddr();String keyip:request.getServletPath();Integer count (Integer)redisUtil.get(key);//首次进入if(countnull||-1count){redisUtil.set(key,1);//设置过期时间redisUtil.expire(key,seconds);return true;}//如果访问次数最大次数则做加1操作if(countmaxCount){redisUtil.incr(key,1);return true;}//此时访问次数大于等于最大次数if(countmaxCount){System.out.println(已经达到该接口限制最大次数count);response.setContentType(text/html;charsetutf-8);response.getWriter().write(请求过于频繁请稍后再试);return false;}}return true;} }注册拦截器 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;Configuration public class InteceptorConfig implements WebMvcConfigurer {Autowiredprivate AccessLimitInterceptor accessLimitInterceptor;Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(accessLimitInterceptor)//添加限流拦截的接口路径.addPathPatterns(/access/accessLimit).addPathPatterns(/main/hello)//添加不限流拦截的路径.excludePathPatterns(/access/login);} } 控制层 import com.example.demo.service.AccessLimit; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController;RestController RequestMapping(access) public class AccessController {ResponseBodyGetMapping(accessLimit)AccessLimit(seconds 60,maxCount 5)public String accessLimit(){return Hellp world!;} }RestController RequestMapping(/main) Slf4j public class MainCOntroller {AutowiredStringRedisTemplate redisTemplate;GetMapping(/hello)AccessLimit(seconds 10,maxCount 2)public String helloo(){return 你好啊;} } 启动测试: 可以看到,两个接口都在限制的时间内有一定数量的访问限制,在redis里也能找到响应的key,从而实现了简单的接口限流
http://www.dnsts.com.cn/news/213398.html

相关文章:

  • 购物网站开发的背景与意义男女插孔做暖暖的试看网站大全
  • 呼和浩特网站开发 千投网页的依托网站
  • 重庆企业网站制作哪家好阜阳做网站哪家好
  • 外贸网站设计风格为男人做购物网站
  • 青海旭云网络做网站需要多少钱河北seo网站优化电话
  • 模块化网站建设 局域网cms源码下载
  • 网站建设需求调查做网站设计怎么样
  • 淘宝做链接有哪些网站可以做网站开发的ui设计
  • 一手房发帖网站怎样做网站建设需要哪些资质
  • 做网站销售话术办公室电脑局域网组建
  • 网站模版库同国外做贸易的网站
  • dsicuz做的网站西安最好的互联网公司排名
  • 怎么参考已有网站做新站网站开发实用技术第二版答案
  • 个人网站带论坛 备案前端培训机构有用吗
  • 投资公司网站开发新乡网站开发的公司电话
  • 职友集一家做公司点评的网站百度权重2的网站
  • 谷歌广告联盟官网网站改版后seo该怎么做
  • 网站建设 保障接单 计划做网站的费属于什么费用
  • 网站建设怎么购买域名建设网站的效果目的及其功能
  • 汝州市住房和城乡规划建设局网站网页视频怎么下载到本地
  • wordpress的网站国内网河源城乡规划建设局网站
  • 做网站ps的素材推广网站概况
  • 网站开发技术有包括58同城黄页推广
  • 微信第三方网站开发教程企业网站建设方案机构
  • 网站建设的风格wordpress主题 手机版
  • 太仓营销型网站建设网站平台建设意见
  • 微网站 具有哪方面的优势做网站用哪个ecalipse
  • 青岛做优化网站哪家好领卷网站怎么做的
  • 网站建设群号如何设计网店店面
  • 司法厅网站建设方案什么是网站建设策划书