最近遇到一个新需求:用户多次点击提交订单发生多次扣款,一开始准备配置数据库事务,但后来发现这种方法白白浪费很多资源,就改为利用接口上的切面对请求做拦截,并将当前登陆的用户存进Redis缓存,废话不说了直接上代码;

AOP的应用(模拟请求拦截器):

/**
* @author YHW
* @ClassName: ApiMemberAspect
* @Description:
* @date 2019/3/21 8:54
*/
@Aspect
@Configuration
public aspect ApiMemberAspect { private Logger logger = LoggerFactory.getLogger(getClass()); private static Gson gson = new Gson(); //切点绑在注解上方便重用!
@Pointcut("@annotation(io.renren.common.annotation.RepetitionCheck)")
public void ApiLogPointCut() { } @Before("ApiLogPointCut()")
public void beforeCheck(JoinPoint joinPoint) throws Throwable {
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
for(int i = 0; i < paramNames.length; i++){
if("payType".equals(paramNames[i]) && paramValues[i] != null){
if(!"membercard".equals(paramValues[i])){
return;
}
}
}
for(int i = 0; i < paramNames.length; i++){
if ("mobile".equals(paramNames[i]) && paramValues[i] != null) {
String phone = (String)paramValues[i];
logger.info(phone);
RedisUtils redisUtils = new RedisUtils();
if(redisUtils.get(phone) != null){
throw new RRException("操作超时,请等待一会后重试");
}else{
redisUtils.set(phone,phone);
}
}
}
} @After("ApiLogPointCut()")
public void afterCheck(JoinPoint joinPoint) throws Throwable{
Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
for(int i = 0; i < paramNames.length; i++){
if ("mobile".equals(paramNames[i]) && paramValues[i] != null) {
String phone = (String)paramValues[i];
logger.info(phone);
RedisUtils redisUtils = new RedisUtils();
if(redisUtils.get(phone) != null){
redisUtils.delete(phone);
}
}
} } @AfterThrowing("ApiLogPointCut()")
public void afterException(JoinPoint joinPoint) throws Throwable{ Object[] paramValues = joinPoint.getArgs();
String[] paramNames = ((CodeSignature) joinPoint.getSignature()).getParameterNames();
for(int i = 0; i < paramNames.length; i++) {
if ("mobile".equals(paramNames[i]) && paramValues[i] != null) {
String phone = (String)paramValues[i];
logger.info(phone);
RedisUtils redisUtils = new RedisUtils();
if(redisUtils.get(phone) != null){
redisUtils.delete(phone);
}
}
} } }

下面是注解类:

/**
* @author YHW
* @ClassName: RepetitionCheck
* @Description:
* @date 2019/3/21 8:58
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RepetitionCheck {
String value() default "";
}

关于Redis就不多提了,自己也是处于只会用用的阶段,以后学习完会单独开一篇Redis专题;

Spring AOP初步总结(三)的更多相关文章

  1. spring AOP详解三

    CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的结束拦截所有父类方法的调用,并顺势织入横切逻辑.我们采用CGLib技术可以编写一个可以为任何类创建织入横切逻辑代理对象 ...

  2. 深入源码解析spring aop实现的三个过程

    Spring AOP的面向切面编程,是面向对象编程的一种补充,用于处理系统中分布的各个模块的横切关注点,比如说事务管理.日志.缓存等.它是使用动态代理实现的,在内存中临时为方法生成一个AOP对象,这个 ...

  3. Spring AOP实现方式三之自动扫描注入【附源码】

    注解AOP实现  这里唯一不同的就是application 里面 不需要配置每个bean都需要配置了,直接自动扫描 注册,主要知识点是怎么通过配置文件得到bean, 注意类前面的@注解. 源码结构: ...

  4. Spring AOP实现方式三【附源码】

    注解AOP实现 源码结构: 1.首先我们新建一个接口,love 谈恋爱接口. package com.spring.aop; /** * 谈恋爱接口 * * @author Administrator ...

  5. Spring AOP初步总结(二)

    该篇为Spring AOP的一个应用案例:系统日志 需求:将任何删除,更改或新增数据库的操作汇总到数据库中 步骤1:编写切面 @Aspect @Component public class SysLo ...

  6. Spring AOP初步总结(一)

    学习AOP有段时间了,一直没空总结一下,导致有些知识点都遗忘了,之后会把以前学过的Spring核心相关的知识点总结一轮... 先大体介绍下Spring AOP的特点(均摘自"Spring i ...

  7. Spring源码窥探之:Spring AOP初步

    AOP(Aspect Oriented Programming):即我们常说的面向切面编程. 什么是AOP?AOP是在我们原来写的代码的基础上,进行一定的包装,比如在方法执行前.方法返回后.方法抛出异 ...

  8. Spring AOP 简介(三)

    Spring AOP 简介 如果说 IoC 是 Spring 的核心,那么面向切面编程就是 Spring 最为重要的功能之一了,在数据库事务中切面编程被广泛使用. AOP 即 Aspect Orien ...

  9. Spring源码窥探之:Spring AOP初步使用

    AOP即面向切面编程.它的底层实际是用了spring的动态代理,具体是JDK的代理还是CGLIB的代理,就视情况而定了.本博客园仅仅作为平时记录,显得有些杂乱无章,如果想了解动态代理,设计模式,请访问 ...

随机推荐

  1. springmvc chrome jsonviewer 一起请求 重复提提交 controller重复执行 2次执行

    情况一: springmvc chrome jsonviewer 一起请求 重复提提交 controller重复执行 2次执行 Chrome浏览器地址栏访问接口url,重复请求问题解决   不论刷新还 ...

  2. windows7 8 mac 安装docker

    安装: 下载 DockerToolbox.exe 苹果的也可以用这个链接下载 一直点击下一步(网络要求很高安装时,网络不好会报错 多点几次就好了)

  3. Tomcat+Nginx实现动静分离

    Tomcat是我们经常用的服务器,轻便快捷,但是数据量大的时候,会影响访问.响应速度,这时Nginx就出现了. Nginx可做反向代理.负载均衡.动态与静态资源的分离的工作,这里我们就用它来做动静分离 ...

  4. webAPI中使用log4net进行日志记录

    1.从nuget下载log4net 2.根据需求配置web.config,或者另外写一个log4net.config文件,各个节点的意义详细查询api <section name="l ...

  5. es6基础系列三:解构赋值

    解构就是ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值(只能用于数组,对象或迭代器).如果解构不成功,则等于undefined,但不能赋值为undefined和null,因为undefi ...

  6. 微信小程序自学第三课:文件作用域,模块化

    一.文件作用域 在 JavaScript 文件中声明的变量和函数只在该文件中有效:不同的文件中可以声明相同名字的变量和函数,不会互相影响. 通过全局函数 getApp() 可以获取全局的应用实例,如果 ...

  7. Linux——DNS

    正向解析和逆向解析  正向域名解析,即DNS解析,是通过域名查询IP的解析方式.  逆向域名解析,即反向DNS解析,是通过IP地址查询域名. [root@localhost ~]# cp /var ...

  8. 图的最小切隔问题Minimum Cuts

    前提条件是这样的:输入一个图(可以是有向图,也可以是无向图,允许平行边存在),我们要做的事情是将这个图切割成两个子图,(切割的定义:将图中的所有顶点分为两个集合A和B,要求这两个集合非空)假设这个图中 ...

  9. 对各种lca算法的理解

    1.RMQ+ST 首先注意这个算法的要素:结点编号,dfs序,结点深度. 首先dfs,求出dfs序,同时求出每个结点的深度.然后st算法,维护深度最小的结点编号(dfs序也可以,因为他们俩可以互相转换 ...

  10. WampServer的安装

    首先安装好Microsoft Visual C++ 然后再安装WampServer 安装过程很简单 错误解决 运行后为黄色图标(成功运行应该为绿色图标) 解决办法: 1.80端口是否被占用 你的80端 ...