文章目录

  • 1.写限流注解
  • 2.redis相关类
  • 3.添加自定义拦截器:
  • 4.controller中使用注解

之前有一篇用aop+redis+lua进行限流的案例:
springboot中使用aop+redis+lua限流

思路是通过前端的cookie中携带的token解析出当前用户,每个用户进行线程隔离,访问次数存入Redis中
用拦截器也可以达到同样限流的目的,在这里同时使用了cookie,用于获取用户信息,代码如下:

1.写限流注解

@Retention(RUNTIME)
@Target(METHOD)
public @interface AccessLimit {int seconds();int maxCount();boolean needLogin() default true;
}

2.redis相关类

/*** @author hzy* @date 2021-12-04* 用于自定义键前缀和过期时间*/
public class BasePrefix {private int expireSeconds;private String prefix;public BasePrefix(String prefix) {//0代表永不过期this(0, prefix);}public BasePrefix( int expireSeconds, String prefix) {this.expireSeconds = expireSeconds;this.prefix = prefix;}public int expireSeconds() {//默认0代表永不过期return expireSeconds;}public String getPrefix() {String className = getClass().getSimpleName();return className+":" + prefix;}
}
@Service
public class RedisServiceImpl implements RedisService {@Resourceprivate RedisTemplate<String, Object> redisTemplate;@Overridepublic void set(String key, Object value, long time) {redisTemplate.opsForValue().set(key,value,time, TimeUnit.SECONDS);}@Overridepublic <T> boolean set(String prefix, String key, T value) {{String str = JsonUtil.toJsonStr(value);if(str == null || str.length() <= 0) {return false;}//生成真正的keyString realKey  = prefix+ key;redisTemplate.opsForValue().set(realKey,str);return true;}}@Overridepublic void set(String key, Object value) {redisTemplate.opsForValue().set(key,value);}@Overridepublic Object get(String key) {return redisTemplate.opsForValue().get(key);}@Overridepublic Boolean del(String key) {return redisTemplate.delete(key);}@Overridepublic Long del(List<String> keys) {return redisTemplate.delete(keys);}@Overridepublic Boolean expire(String key, long time) {return redisTemplate.expire(key,time,TimeUnit.SECONDS);}@Overridepublic Long getExpire(String key) {return redisTemplate.getExpire(key,TimeUnit.SECONDS);}@Overridepublic Boolean hasKey(String key) {return redisTemplate.hasKey(key);}@Overridepublic Long incr(String key, long delta) {return redisTemplate.opsForValue().increment(key,delta);//增加}@Overridepublic Long incr(String key) {return redisTemplate.opsForValue().increment(key);}@Overridepublic Long decr(String key, long delta) {return redisTemplate.opsForValue().decrement(key,delta);}//还有一些操作list set hash等的操作就省略了
}

3.添加自定义拦截器:

public class AccessInterceptor implements HandlerInterceptor {public static final String COOKI_NAME_TOKEN = "token";@AutowiredIUserService userService;@AutowiredRedisService redisService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {if(handler instanceof HandlerMethod) {User user = getUser(request, response);ThreadlocalUser.setUser(user);//进行线程隔离//用HandlerMethod hm = (HandlerMethod)handler;AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);if(accessLimit == null) {return true;}int seconds = accessLimit.seconds();int maxCount = accessLimit.maxCount();boolean needLogin = accessLimit.needLogin();String key = request.getRequestURI();if(needLogin) {if(user == null) {render(response, "SESSION_ERROR");return false;}key += "_" + user.getId();}else {//do nothing}//       AccessKey ak = AccessKey.withExpire(seconds);String ak = "access";Integer count = (Integer) redisService.get("access"+key);if(count  == null) {redisService.set(ak+key, 1);}else if(count < maxCount) {redisService.incr(ak+key);}else {render(response, "ACCESS_LIMIT_REACHED");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(ResponseResult.error(cm));out.write(str.getBytes("UTF-8"));out.flush();out.close();}private User getUser(HttpServletRequest request, HttpServletResponse response) {String paramToken = request.getParameter(COOKI_NAME_TOKEN);//获取请求中的token参数String cookieToken = getCookieValue(request, COOKI_NAME_TOKEN);if(StringUtils.isEmpty(cookieToken) && StringUtils.isEmpty(paramToken)) {return null;}String token = StringUtils.isEmpty(paramToken)?cookieToken:paramToken;return userService.getByToken(response, token);}private String getCookieValue(HttpServletRequest request, String cookiName) {Cookie[]  cookies = request.getCookies();if(cookies == null || cookies.length <= 0){return null;}for(Cookie cookie : cookies) {if(cookie.getName().equals(cookiName)) {return cookie.getValue();}}return null;}}

其中ThreadlocalUser类:

public class ThreadlocalUser {private static ThreadLocal<User> userHolder = new ThreadLocal<User>();public static void setUser(User user) {userHolder.set(user);}public static User getUser() {return userHolder.get();}
}

4.controller中使用注解

 @AccessLimit(seconds=5, maxCount=5, needLogin=true)@RequestMapping(value="/path", method=RequestMethod.GET)@ResponseBodypublic Result<String> getMiaoshaPath(HttpServletRequest request, MiaoshaUser user,@RequestParam("goodsId")long goodsId,@RequestParam(value="verifyCode", defaultValue="0")int verifyCode) {if(user == null) {return Result.error(CodeMsg.SESSION_ERROR);}boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);if(!check) {return Result.error(CodeMsg.REQUEST_ILLEGAL);}String path  =miaoshaService.createMiaoshaPath(user, goodsId);return Result.success(path);}

用拦截器+注解+cookie进行简单限流访问案例相关推荐

  1. springboot中使用lua脚本+aop作限流访问案例代码

    文章目录 1.限流注解 2.redis配置 3.aop配置 4.controller层测试 拓展:Atomic类的学习 lua脚本学习 1.限流注解 @Target(ElementType.METHO ...

  2. springboot + 拦截器 + 注解 实现自定义权限验证

    springboot + 拦截器 + 注解 实现自定义权限验证 最近用到一种前端模板技术:jtwig,在权限控制上没有用springSecurity.因此用拦截器和注解结合实现了权限控制. 1.1 定 ...

  3. redis实现简单限流

    首先我们给出限流的定义: 1. 限定某个行为在指定时间内被允许的最大次数 2. 限定某个用户的某个行为在指定时间内被允许的最大次数 其实二者差不多,前面一句是限定所有人,后面的是限定了每个用户 注意 ...

  4. Spring MVC拦截器+注解方式实现防止表单重复提交

    原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过. 1.新建注解: /*** <p&g ...

  5. struts拦截器+注解实现网络安全要求中的日志审计功能

    J2EE项目中出于安全的角度考虑,用户行为审计日志功能必不可少,通过本demo可以实现如下功能: 1.项目中记录审计日志的方法. 2.struts拦截器的基本配置和使用方法. 3.struts拦截器中 ...

  6. 域名微信拦截html代码,多域名下获取微信openId,通过拦截器注解实现,减少代码量以及业务混淆...

    一个注解,一个拦截器,还有一个中转html页(来源网上,稍微修改),原理看拦截器的类注解.package com.xxx.admin.interceptor; import com.xxx.core. ...

  7. 利用mybatis拦截器注解处理sql

    首先@Intercepts注解 可以看这篇文章https://blog.csdn.net/weixin_43505211/article/details/128050083 建个类 实现 Interc ...

  8. Struts2【拦截器】就是这么简单

    2019独角兽企业重金招聘Python工程师标准>>> 什么是拦截器 拦截器Interceptor.....拦截器是Struts的概念,它与过滤器是类似的...可以近似于看作是过滤器 ...

  9. 基于Spring拦截器实现拦截器注解

    需求描述: 对指定资源(方法或者类)进行权限控制. 解决方案 在需要权限控制的资源,加上权限控制注解 软件版本 JAVA JDK 1.8 Spring 4.3.6.RELEASE 实现细节 注解接口 ...

最新文章

  1. The Power of Ten – Rules for Developing Safety Critical Code
  2. ansys结构分析单元与应用_结构动力学中的时域分析(3) —— 基于ANSYS的实现
  3. golang mysql条件查询_mysql – 将变量传递给GoLang查询
  4. 朴宥拉短片突破了几百万的观看量
  5. MFC 教程【4_消息映射的实现】
  6. android 代码混淆配置
  7. 全球Top10最佳移动统计分析sdk
  8. AndroidDeveloper Weekly No.5
  9. 微信开发:getLocation签名失效的问题
  10. 短视频标题自动生成工具,助你打造爆款标题
  11. 浅谈PMSM电机控制之Clark变换(详细推导及MATLAB仿真)
  12. abb机器人编程指令写字_最全的ABB机器人编程指令与函数
  13. 竞价推广过程中最难的问题是什么?
  14. 问题解决:系统上禁止运行脚本。有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID=135170 中的about_Execution_Policies
  15. 【安规】电气间隙和爬电距离如何确定
  16. n行数字组成的数字三角形详解
  17. 数值分析中对有效数字的定义
  18. js代码设置节点的属性
  19. qt动画框架(三) 自定义tab滑动导航栏
  20. python列表元素0的移动_【Python】列表元素零的移动

热门文章

  1. mysql查看数据倾斜_深入理解hadoop数据倾斜
  2. mysql迁移之后读取速度变慢_如何解决数据库迁移之后变慢的问题
  3. python中的列表是指针吗_Python中的指针——到底指什么(二)
  4. if python 判断函数返回值_Python函数的返回值和作用域
  5. 吴恩达 matlab,吴恩达机器学习记录--Matlab 一些基本操作
  6. debian linux系统下载工具,Debian For Linux
  7. html实现旅游网站代码_[资源推荐] 必须收藏的两个查找论文和代码实现的网站!...
  8. 【推荐系统】基于物品的协同过滤算法
  9. 有些事情你不做,总有人替你做了-2020-07-28
  10. ACL 2021 | 为什么机器阅读理解模型会学习走捷径?