spring boot 学习(九)小工具篇:?秒防刷新
注解 + 拦截器:?秒防刷新
小工具篇:工具许多都是我以前在 github 之类开源平台找到的小工具类,作者的信息什么的许多都忘了。先说声不好意思了。若有相关信息,麻烦提醒一下~
解释
所谓的?秒防刷新,其实就是限制用户在某个时间内对某个 Controller 的访问时间限制。最常见的,比如学校教务系统(正方)的3s防刷新。虽然我不知道正方系统具体是如何实现的,不过可以通过 注解+拦截器 来实现。
前期准备
关于 注解+拦截器,我在上一篇小工具中已经有所介绍。
同时,关于系统轮询的问题,可以使用 @Scheduled 来进行一个全系统记录的轮询,但真的没必要……我觉得可以使用 java 自带的定时器小工具 Timer 与 TimerTask。
* Timer 是一种定时器工具,用来在一个后台线程计划执行指定任务。
* TimerTask 一个抽象类,它的子类或者重写run方法代表一个可以被Timer计划的任务
参考资料:(Timer与TimerTask详解)http://blog.csdn.net/ahxu/article/details/249610
正式开工
- 自定义异常类
HttpServletException : 用于记录http请求或响应异常。
RequestLimitException : 用于记录用户HTTP请求超出设定的限制。
public class RequestLimitException extends Exception {
public RequestLimitException() {
super("HTTP请求超出设定的限制");
}
public RequestLimitException(String message) {
super(message);
}
public RequestLimitException(String message, Throwable cause){
super(message, cause);
}
}
- 注解类 RequestLimit.java
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface RequestLimit { //允许访问的次数,默认值MAX_VALUE
int count() default Integer.MAX_VALUE; // 时间段,单位为毫秒,默认值一分钟
long time() default 60000; }
- 拦截器 RequestLimitContract.java
@Aspect
@Component
public class RequestLimitContract {
private static final Logger logger = LoggerFactory.getLogger(RequestLimitContract.class); //用于存储记录
private Map<String, Integer> redisTemplate=new HashMap<String,Integer>(); @Before("within(@org.springframework.stereotype.Controller *) && @annotation(limit)")
public void requestLimit(final JoinPoint joinPoint, RequestLimit limit) throws RequestLimitException {
try {
//获取 HttpServletRequest 参数
Object[] args = joinPoint.getArgs();
HttpServletRequest request = null;
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof HttpServletRequest) {
request = (HttpServletRequest) args[i];
break;
}
}
if (request == null) {
logger.error("方法中缺失HttpServletRequest参数");
throw new HttpServletException("方法中缺失HttpServletRequest参数");
} String ip = request.getLocalAddr();
String url = request.getRequestURL().toString();
final String key = "req_limit_".concat(url).concat(ip); System.out.println("ip = "+ip+"\n"+" url = "+url+"\n"+" key = "+key); if(redisTemplate.get(key)==null || redisTemplate.get(key)==0){
redisTemplate.put(key,1);
}else{
redisTemplate.put(key,redisTemplate.get(key)+1);
}
int count = redisTemplate.get(key);
if (count > 0) {
Timer timer= new Timer();
TimerTask task = new TimerTask(){ //创建一个新的计时器任务。
@Override
public void run() {
if(!key.equals("")) {
redisTemplate.remove(key);
}
}
};
timer.schedule(task, limit.time());
//安排在指定延迟后执行指定的任务。task : 所要安排的任务。limit.time() : 执行任务前的延迟时间,单位是毫秒。
}
if (count > limit.count()) {
logger.info("用户IP[" + ip + "]访问地址[" + url + "]超过了限定的次数[" + limit.count() + "]");
throw new RequestLimitException();
}
} catch (RequestLimitException e) {
throw e;
} catch (Exception e) {
logger.error("发生异常: ", e);
}
}
}
- 控制器
注意方法中一定要有 HttpServletRequest 参数!!!不然会抛出 HttpServletException 异常。
@ResponseBody
@RequestMapping("/hello")
@RequestLimit(count = 10)
public String hello(HttpServletRequest request) {
return "Hello World";
}
效果截图
1. 正常访问
访问受限
服务器后台
spring boot 学习(九)小工具篇:?秒防刷新的更多相关文章
- spring boot 学习(七)小工具篇:表单重复提交
注解 + 拦截器:解决表单重复提交 前言 学习 Spring Boot 中,我想将我在项目中添加几个我在 SpringMVC 框架中常用的工具类(主要都是涉及到 Spring AOP 部分知识).比如 ...
- Spring boot 学习 九
一:经过试验发现,如果使用如下的Controller(@RequestBody), 前台POST的请求body只能是JSON,如果是form-data, X-www-form-urlencoded 或 ...
- 学习 Spring Boot 知识看这一篇就够了
从2016年因为工作原因开始研究 Spring Boot ,先后写了很多关于 Spring Boot 的文章,发表在技术社区.我的博客和我的公号内.粗略的统计了一下总共的文章加起来大概有六十多篇了,其 ...
- Spring boot学习1 构建微服务:Spring boot 入门篇
Spring boot学习1 构建微服务:Spring boot 入门篇 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...
- spring boot 结合Redis 实现工具类
自己整理了 spring boot 结合 Redis 的工具类引入依赖 <dependency> <groupId>org.springframework.boot</g ...
- Spring Boot学习笔记2——基本使用之最佳实践[z]
前言 在上一篇文章Spring Boot 学习笔记1——初体验之3分钟启动你的Web应用已经对Spring Boot的基本体系与基本使用进行了学习,本文主要目的是更加进一步的来说明对于Spring B ...
- spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战
SpringBoot + Redis +SpringSession 缓存之实战 前言 前几天,从师兄那儿了解到EhCache是进程内的缓存框架,虽然它已经提供了集群环境下的缓存同步策略,这种同步仍然需 ...
- 我的Spring Boot学习记录(二):Tomcat Server以及Spring MVC的上下文问题
Spring Boot版本: 2.0.0.RELEASE 这里需要引入依赖 spring-boot-starter-web 这里有可能有个人的误解,请抱着怀疑态度看. 建议: 感觉自己也会被绕晕,所以 ...
- Spring Boot 学习方法论-如何正确的入门 Spring Boot
想要入门 Spring Boot,那么什么样的教程是符合初学者学习的(没有太多的Java基础但有一些程序基础或者软件编程知识). 这恰好能够勾出很多问题,比如是文章图文教程适合还是视频教程适合零基础初 ...
随机推荐
- 01: 企业微信API开发前准备
目录:企业微信API其他篇 01: 企业微信API开发前准备 02:消息推送 03: 通讯录管理 04:应用管理 目录: 1.1 术语介绍 1.2 开发步骤 1.1 术语介绍返回顶部 参考文档:htt ...
- 20145105 《Java程序设计》实验三总结
实验三 一. 实验内容 结对修改实验一代码,重点学习重构 二. 实验步骤 下载结伴同学的实验一代码 初始代码 进行整数.小数和负数的多组数据测试,发现一个运行错误的例子 分析后 ...
- jquery插件--问题类(新增&&删除)简易版
HTML: <!doctype html> <head> <meta charset="utf-8" /> <script src=&qu ...
- List集合实现简易学生管理
题目: 代码: package org.wlgzs; import java.util.ArrayList; import java.util.List; import java.util.Scann ...
- ubuntu下桌面假死处理方法(非重启)
一.背景 2018/05/22,就在这一天,进入ubuntu的桌面后随便点击任何位置均无法响应,此时又不想重启,遂出此文 二.解决方案 2.1 关掉Xorg进程 2.1.1按下ctrl+alt+F1进 ...
- SQL NULL
表 select CHARACTER_MAXIMUM_LENGTH from information_schema.columns where table_name= 'Alliance' selec ...
- Where is HttpContent.ReadAsAsync?
It looks like it is an extension method (in System.Net.Http.Formatting): HttpContentExtensions Class ...
- 【错误解决】SVN常见错误及解决方式
1.Error while creating module:org.apache.subversion.javahl.ClientException:Authorization failed svn: ...
- 2017 ACM/ICPC 新疆赛区 I 题 A Possible Tree 带权并查集
传送门 题意:给定一棵带权树的形态, 但是并不知道每天条边的具体权重. 然后给m个信息, 信息格式为u v val, 表示在树上u 到 v 的路径上经过的边的权重的异或和为val, 问前面最多有多少个 ...
- C指针的一些知识
原文:http://blog.csdn.net/soonfly/article/details/51131141 前言:复杂类型说明 要了解指针,多多少少会出现一些比较复杂的类型,所以我先介绍一下如何 ...