原文:http://www.cnblogs.com/xiaoyangjia/p/3762150.html?utm_source=tuicool

我们需要根据IP去限制用户单位时间的访问次数,防止刷手机验证码,屏蔽注册机等,使用注解就非常灵活了

1 定义注解

  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.METHOD)
  3. @Documented
  4. //最高优先级
  5. @Order(Ordered.HIGHEST_PRECEDENCE)
  6. public @interface RequestLimit {
  7. /**
  8. *
  9. * 允许访问的次数,默认值MAX_VALUE
  10. */
  11. int count() default Integer.MAX_VALUE;
  12.  
  13. /**
  14. *
  15. * 时间段,单位为毫秒,默认值一分钟
  16. */
  17. long time() default 60000;
  18. }

 2 实现注解

  1. @Aspect
  2. @Component
  3. public class RequestLimitContract {
  4. private static final Logger logger = LoggerFactory.getLogger("RequestLimitLogger");
  5. @Autowired
  6. private RedisTemplate<String, String> redisTemplate;
  7.  
  8. @Before("within(@org.springframework.stereotype.Controller *) && @annotation(limit)")
  9. public void requestLimit(final JoinPoint joinPoint, RequestLimit limit) throws RequestLimitException {
  10.  
  11. try {
  12. Object[] args = joinPoint.getArgs();
  13. HttpServletRequest request = null;
  14. for (int i = 0; i < args.length; i++) {
  15. if (args[i] instanceof HttpServletRequest) {
  16. request = (HttpServletRequest) args[i];
  17. break;
  18. }
  19. }
  20. if (request == null) {
  21. throw new RequestLimitException("方法中缺失HttpServletRequest参数");
  22. }
  23. String ip = HttpRequestUtil.getIpAddr(request);
  24. String url = request.getRequestURL().toString();
  25. String key = "req_limit_".concat(url).concat(ip);
  26. long count = redisTemplate.opsForValue().increment(key, 1);
  27. if (count == 1) {
  28. redisTemplate.expire(key, limit.time(), TimeUnit.MILLISECONDS);
  29. }
  30. if (count > limit.count()) {
  31. logger.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]");
  32. throw new RequestLimitException();
  33. }
  34. } catch (RequestLimitException e) {
  35. throw e;
  36. } catch (Exception e) {
  37. logger.error("发生异常: ", e);
  38. }
  39. }
  40. }

3 自定义Exception

  1. public class RequestLimitException extends Exception {
  2. private static final long serialVersionUID = 1364225358754654702L;
  3.  
  4. public RequestLimitException() {
  5. super("HTTP请求超出设定的限制");
  6. }
  7.  
  8. public RequestLimitException(String message) {
  9. super(message);
  10. }
  11.  
  12. }

4 在Controller中使用

  1. @RequestLimit(count=100,time=60000)
  2. @RequestMapping("/test")
  3. public String test(HttpServletRequest request, ModelMap modelMap) {
  4. //TODO
  5. }

[SpringMVC+redis]自定义aop注解实现控制器访问次数限制的更多相关文章

  1. [SpringMVC]自定义注解实现控制器访问次数限制

    我们需要根据IP去限制用户单位时间的访问次数,防止刷手机验证码,屏蔽注册机等,使用注解就非常灵活了 1 定义注解 @Retention(RetentionPolicy.RUNTIME) @Target ...

  2. SpringMVC中的常用注解

    RequestParam 作用: 用于  将请求参数区数据  映射到  功能处理方法的参数上. 属性: value  请求参数中的名称 required   请求参数中是否必须提供此参数. 默认值: ...

  3. Spring aop注解失效

    问题 在spring 中使用 @Transactional . @Cacheable 或 自定义 AOP 注解时,对象内部方法中调用该对象的其他使用aop机制的方法会失效. @Transactiona ...

  4. 使用Redis+自定义注解实现接口防刷

    最近开发了一个功能,需要发送短信验证码鉴权,考虑到短信服务需要收费,因此对此接口做了防刷处理,实现方式主要是Redis+自定义注解(需要导入Redis的相关依赖,完成Redis的相关配置,gs代码,这 ...

  5. SpringMVC强大的数据绑定(2)——第六章 注解式控制器详解

    SpringMVC强大的数据绑定(2)——第六章 注解式控制器详解 博客分类: 跟开涛学SpringMVC   6.6.2.@RequestParam绑定单个请求参数值 @RequestParam用于 ...

  6. SpringMVC传统风格控制器和基于注解的控制器

    SpringMVC的DispatcherServlet 之前说过springMVC是使用Servlet作为控制器,就是这个用于调度的DispatcherServlet了.这个是servlet,可以根据 ...

  7. 【spring springmvc】springmvc使用注解声明控制器与请求映射

    目录 概述 壹:注解说明 贰:实现注解声明控制器与请求映射 一:使用controller 二:配置包扫描与视图解析器 1.配置包扫描 2.配置试图解析器 三:配置部署描述符 1.读取spring-mv ...

  8. [译]SpringMVC自定义验证注解(SpringMVC custom validation annotations)

    在基于SpringMVC框架的开发中,我们经常要对用户提交的字段进行合法性验证,比如整数类型的字段有个范围约束,我们会用@Range(min=1, max=4).在实际应用开发中,我们经常碰到一些自己 ...

  9. springMVC基于注解的控制器

    springMVC基于注解的控制器 springMVC基于注解的控制器的优点有两个: 1.控制器可以处理多个动作,这就允许将相关操作写在一个类中. 2.控制器的请求映射不需要存储在配置文件中.使用re ...

随机推荐

  1. HDU5748---(记录每个元素的 最长上升子序列 nlogn)

    分析: 给一个序列,求出每个位置结尾的最长上升子序列 O(n^2) 超时 #include "cstdio" #include "algorithm" #def ...

  2. Python基础(4)_集合、布尔类型

    一.集合 集合的作用一:关系运算集合的作用二:去重 定义集合:集合内的元素必须是唯一的:集合内的元素必须是可hash的,也是就不可变类型:集合是无序的 s={'egon',123,'egon','1' ...

  3. tr/td

    在HTML中,tr代表行,td代表列. 说明: 1.tr与td必须一起使用,并且输入的内容必须在td里面: 2.td必须在tr里面,表示在一行中的列: 3.在一个tr里面,有x个td,就表示在这一行里 ...

  4. Oracle exp

    --导出表exp userid=hr/oracle123 tables=employees direct=y file=/u01/employees.dmp log=/u01/employees.lo ...

  5. 原型和JS内置对象

    原型 1.定义 每一个对象都有原型 原型仍然是一个对象 模拟实现面向对象的继承性 2.原型链 对象的原型还有原型 对象除了可以使用自有属性还可以继承原型上的属性 3.获取原型 对象.__proto__ ...

  6. Java==与equals方法的区别

    摘自:http://www.cnblogs.com/dolphin0520/p/3592500.html 1.对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等: 如果作用于引 ...

  7. [ LDAP ] LDAP服务搭建及应用

    ldap 搭建及应用 node1: 192.168.118.14node2: 192.168.118.25 ldap server : 192.168.118.14 1. 安装LDAP服务器 [roo ...

  8. 图的遍历[DFS][BFS]

    #include<iostream> #include<iostream> #include<cstring> #include<queue> #inc ...

  9. 对tmemorystream的一些改进_delphi教程

    http://www.cnblogs.com/linyawen/archive/2010/12/11/1903072.html 怎么又是关于Stream的,呵呵,应该说只是最近比较关心程式的效率问题, ...

  10. php关于private、protected、public的区别

    一句话总结: private 自己的 protected 父亲的 public 大众的