spring aop 、Redis实现拦截重复操作
一、问题:项目中有一些重复操作的情况,比如:
1.从场景有用户快速点击提交按钮,或者postMan测试时快速点击
2.从业务上来说,用户注册、用户下单等
3.黑客攻击
二、解决办法
1、使用springAop、Redis
2、代码
/**
* 2020/7/22 9:59 AM
*
* @author shoo
* @describe 校验重复操作 (aop实现)
*/
@Aspect
@Component
public class ParaLogAspect { private static final Logger logger = LoggerFactory.getLogger(ParaLogAspect.class); @Autowired
private RedisTemplate<String, Object> redisTemplate; //定义一个切点,要切的类、方法
@Pointcut("execution(* com.meritdata.cloud.middleplatform.dataservice.account.integral.controller.*.*(..))" +
"||execution(* com.meritdata.cloud.middleplatform.dataservice.account.platformBase.controller.*.*(..))" +
"||execution(* com.meritdata.cloud.middleplatform.dataservice.account.storeConsume.controller.*.*(..))" +
"||execution(* com.meritdata.cloud.middleplatform.dataservice.account.vipcard.controller.*.*(..))" +
"||execution(* com.meritdata.cloud.middleplatform.dataservice.shell.controller.*.*(..))")
public void authRepeat(){ } @Around("authRepeat()")
public Object authRepeat(ProceedingJoinPoint joinPoint) throws Throwable{ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
StringBuffer body = new StringBuffer();
Object[] arguments = joinPoint.getArgs();
//获取方法的参数
//注意这里只取了第一个参数,如果想兼容多个参数的方法请自行处理
if(arguments.length!=0){
try {
Map<String, Object> params = params = (Map<String, Object>)arguments[0];
for (String key:params.keySet()
) {
body.append(key).append("=").append(params.get(key)).append("&");
} }catch (Exception ex){
logger.info("=====方法接收参数[{}]",arguments[0].toString());
}
}
// key:请求者IP+请求URL+参数
String key = request.getRemoteAddr() + ";" + request.getRequestURL().toString() + "?" + body.toString();
logger.info("====key[{}]",key.substring(0,key.length()-1)); Object obj = null;
Object[] args = joinPoint.getArgs();
//重复提交校验
if(!authRepeat(key)){
logger.info("重复提交,key[{}]",key);
return MapResult.build("请勿频繁操作",false);
}
//不是重复提交则继续主进程
try {
obj = joinPoint.proceed(args);
} catch (Throwable e) {
logger.error("重复操作校验环绕通知出错", e);
}
return obj;
} //重复提交校验
// Redis的increment方法:把key的值加上指定数值,如果key不存在则默认创建,该操作是单线程的
private boolean authRepeat(String key){ long repeat = redisTemplate.opsForValue().increment(key,1);
logger.info("repeat:[{}]",repeat);
if(repeat>1){
return false;
}
redisTemplate.expire(key,1, TimeUnit.SECONDS);
return true;
}
}
3.说明
a、首先用springAop切入需要校验的类或者方法,这里用的是环绕通知(around),如果一秒内操作次数超过一次则返回错误提示请勿频繁操作
b、校验规则是 请求者IP+请求URL+方法参数
c、Redis的increment是单线程的原子操作
三、测试
用locust启动十个用户同时访问用户注册接口,数据库中只注册成功了一个数据,剩余的都提示请勿频繁操作
spring aop 、Redis实现拦截重复操作的更多相关文章
- 今日份学习:写一些代码 (Spring+AOP+Redis+MySQL练习)
笔记 Spring+AOP+Redis+MySQL练习 1. 启动docker->mysql docker run --name mysql -v e:\docker:/var/lib/mysq ...
- TinyFrame再续篇:整合Spring AOP实现日志拦截
上一篇中主要讲解了如何使用Spring IOC实现依赖注入的.但是操作的时候,有个很明显的问题没有解决,就是日志记录问题.如果手动添加,上百个上千个操作,每个操作都要写一遍WriteLog方法,工作量 ...
- Spring AOP原理及拦截器
原理 AOP(Aspect Oriented Programming),也就是面向方面编程的技术.AOP基于IoC基础,是对OOP的有益补充. AOP将应用系统分为两部分,核心业务逻辑(Core bu ...
- Spring aop 实现异常拦截
使用aop异常挂载功能可以统一处理方法抛出的异常,减少很多重复代码,实现如下: 1.实现ThrowAdvice public class ExceptionHandler implements Thr ...
- 从零开始学 Java - Spring AOP 拦截器的基本实现
一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...
- Java - Spring AOP 拦截器的基本实现
一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...
- Spring学习总结(15)——Spring AOP 拦截器的基本实现
一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...
- Spring AOP无法拦截内部方法调用
当在同一个类中,A方法调用B方法时,AOP无法工作的问题 假设一个接口里面有两个方法: package demo.long; public interface CustomerService { pu ...
- 【Spring AOP】AOP介绍(一)
AOP(Aspect Oriented Programming) 面向切面编程,是Spring框架的一个重要组件. AOP应该算是对OOP(面向对象编程)的补充和完善.OOP引入封装.继承.多态等概念 ...
随机推荐
- mysql运维-slave_skip_errors
1 简介 mysql在主从复制过程中,由于各种的原因,从服务器可能会遇到执行BINLOG中的SQL出错的情况,在默认情况下,服务器会停止复制进程,不再进行同步,等到用户自行来处理. sla ...
- 全排列算法--递归实现(Java)
求一个n阶行列式,一个比较简单的方法就是使用全排列的方法,那么简述以下全排列算法的递归实现. 首先举一个简单的例子说明算法的原理,既然是递归,首先说明一下出口条件.以[1, 2]为例 首先展示一下主要 ...
- JS+CSS+HTML实现“代码雨”类似黑客帝国文字下落效果
HTML代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <l ...
- 管理机--Jumpserver由docker搭建
一.环境准备 使用Centos7.0及以上版本,(网要好哦) 二.安装docker 1,下载,安装,启动 docker yum -y install docker #安装docker ...
- JAVA中使用JSONArray和JSONObject
json 就是一个键对应一个值,简单的一对一关系. JSONObject json对象,就是一个键对应一个值(键值对),使用的是大括号{ },如:{key:value} JSONArray jso ...
- 使用switch计算出某年某月某日是今年的第几天,输出一直是当月天数
package com.cx.Switch; import java.util.Scanner; /** * 计算出某年某月某日是今年的第几天 * 使用switch */ public class S ...
- CSharpFlink分布式实时计算,OutOfMemoryException异常,你意想不到的原因。
目录 一.测试过程及问题 二.问题排查及分析过程 三.问题分析及解决过程 四.问题解决初步结果 一.测试过程及问题 从昨天15点左右开始测试,1个主节点,10个计算节点,1000个数据点,每个数据点3 ...
- 2,flask URL进阶
video5 flask特点: 1,为框架,简介,高扩展性. 2,flask相关依赖(jinja2,werkzeug)设计优秀. 3,开发高效,如SQL的ORM video6 debug模式 我只推荐 ...
- Python_环境搭建_jupyterNotebook的使用
# @ Author : Collin_PXY # 虚拟环境的创建及Jupyter Notebook的基本使用 # Anaconda 和 Jupter Notebook的使用: # 首先得需要安装 A ...
- 【JVM第七篇】执行引擎
写在前面的话:本文是在观看尚硅谷JVM教程后,整理的学习笔记.其观看地址如下:尚硅谷2020最新版宋红康JVM教程 执行引擎是Java虚拟机中的核心组成部分. 执行引擎的作用就是解析虚拟机字节码指令, ...