SpringBoot AOP实现接口次数访问统计
1 理论基础
1.1 AOP是什么
-
面向切面编程(AOP,Aspect Oriented Programming)
-
可以通过预编译方式和运行时动态代理,实现在不修改源代码的情况下,给程序动态增强功能的的一种技术
1.2 AOP能做什么
- 统计接口访问次数
- 数据库事务处理
- 增强功能:在不改动源代码的基础上,为接口增加一些额外的功能
2 Demo代码
2.1 引入依赖
<dependencies><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-webartifactId>dependency><dependency><groupId>org.aspectjgroupId><artifactId>aspectjrtartifactId><version>1.9.4version>dependency><dependency><groupId>org.aspectjgroupId><artifactId>aspectjweaverartifactId><version>1.9.4version>dependency><dependency><groupId>cglibgroupId><artifactId>cglibartifactId><version>3.2.12version>dependency><dependency><groupId>com.alibabagroupId><artifactId>fastjsonartifactId><version>1.2.70version>dependency><dependency><groupId>org.springframework.bootgroupId><artifactId>spring-boot-starter-testartifactId><scope>testscope><exclusions><exclusion><groupId>org.junit.vintagegroupId><artifactId>junit-vintage-engineartifactId>exclusion>exclusions>dependency>dependencies>
2.2 API访问历史统计
/*** API访问历史统计*/
@Component
@Aspect
public class ApiVisitHistory {private Logger log = LoggerFactory.getLogger(ApiVisitHistory.class);private ThreadLocal<Long> startTime = new ThreadLocal<>();/*** 定义切面* - 此处代表com.smile.demo.controller包下的所有接口都会被统计*/@Pointcut("execution(* com.smile.demo.controller..*.*(..))")public void pointCut(){}/*** 在接口原有的方法执行前,将会首先执行此处的代码*/@Before("pointCut()")public void doBefore(JoinPoint joinPoint) {startTime.set(System.currentTimeMillis());//获取传入目标方法的参数Object[] args = joinPoint.getArgs();log.info("类名:{}", joinPoint.getSignature().getDeclaringType().getSimpleName());log.info("方法名:{}", joinPoint.getSignature().getName() );// 计数AtomicCounter.getInstance().increase();}/*** 只有正常返回才会执行此方法* 如果程序执行失败,则不执行此方法*/@AfterReturning(returning = "returnVal", pointcut = "pointCut()")public void doAfterReturning(JoinPoint joinPoint, Object returnVal) {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();log.info("URI:[{}], 耗费时间:[{}] ms, 访问次数:{}", request.getRequestURI(), System.currentTimeMillis() - startTime.get(), AtomicCounter.getInstance().getValue());}/*** 当接口报错时执行此方法*/@AfterThrowing(pointcut = "pointCut()")public void doAfterThrowing(JoinPoint joinPoint) {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();log.info("接口访问失败,URI:[{}], 耗费时间:[{}] ms", request.getRequestURI(), System.currentTimeMillis() - startTime.get());}
}
2.3 定义测试接口
@RestController
@RequestMapping("/demo/aop")
public class HelloController {@GetMapping("hello")public String hello() {return "hello World!";}
}
@RestController
@RequestMapping("/demo/aop")
public class ErrorController {@GetMapping("error")public String error() {int i = 1 / 0;return "测试报错的AOP方法";}
}
2.4 单例计数器
/*** 计数器,统计当前执行的任务数**/
public class AtomicCounter {private static final AtomicCounter atomicCounter = new AtomicCounter();/*** 单例,不允许外界主动实例化*/private AtomicCounter() { }public static AtomicCounter getInstance() {return atomicCounter;}private static AtomicInteger counter = new AtomicInteger();public int getValue() {return counter.get();}public int increase() {return counter.incrementAndGet();}public int decrease() {return counter.decrementAndGet();}}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
