1、简介
上文我们学习了AOP面向切面编程的基础和相关知识,了解到它可以在不修改源代码的基础上为程序打造监控日志,本文我们开展实践,利用AOP切面技术为主流RESTFul-API接口打造一个统一的访问日志,实现登录IP、访问方法、传入参数等信息的记录。
2、项目架构及思路
项目架构:作用于标准RESTFul-API接口,暂不设置登录和认证机制。
思路:在不修改任何接口源代码的基础上,新增一个Before切面,切入点包含API接口下面的所有类、接口、方法,记录传入参数。
3、日志架构
(1)接口IP地址:由ServletRequestAttributes(getRequestURL())提供。ServletRequestAttributes是SpringMVC封装的ThreadLocal,保存了每次Http请求的HttpServletRequest对象。
(2)访问接口对方IP地址:由ServletRequestAttributes(getRemoteAddr())提供。
(3)接口类路径名称:由切面连接点JoinPoint(getSignature().getDeclaringTypeName())提供。
(4)接口方法名称:由切面连接点JoinPoint(getSignature().getName())提供。
(5)传入参数:由切面连接点JoinPoint(getArgs())提供。
4、项目结构树
这里原来有一个实体类Book和一个RESTFul-API接口BookRepository用来实现查询get、修改put、新增post、删除delete等基本操作,对接口我们不做任何源代码修改,在顶层package下面创建一个Aoplog类,用来实现AOP切面和访问日志输出。
5、Aoplog代码实现
package com.example.demohelloworld.restful;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
@Component
@Aspect
public class Aoplog {
//定义日志输出
Logger logger= LoggerFactory.getLogger(this.getClass());
//定义切入点
@Pointcut("execution(* com.example.demohelloworld.restful.APIRepository.*.*(..))")
public void getlog(){
}
//构建一个Before前置通知,在方法执行之前执行,可获取传入参数
@Before(value = "getlog()")
public void before(JoinPoint joinPoint){
//通过ServletRequestAttributes获取Http访问接口请求信息
ServletRequestAttributes attributes= (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request=attributes.getRequest();
//接口IP地址
logger.info("url={}",request.getRequestURL());
//访问接口对方IP地址
logger.info("ip={}",request.getRemoteAddr());
//接口类路径名称
logger.info("class={}",joinPoint.getSignature().getDeclaringTypeName());
//接口方法名称
logger.info("method={}",joinPoint.getSignature().getName());
//传入参数,格式为Object[],使用Arrays.deepToString进行转化
logger.info("args={}", Arrays.deepToString(joinPoint.getArgs()));
}
}
6、启动测试
我们启动项目,利用POSTMAN访问API接口:
findById查询单条数据,访问日志输出如下:
findAll批量查询,访问日志输出如下,传入参数我们加入了分页,每页条数和按ID倒叙排列:
save新增Book数据,访问日志输出如下:
7、总结
AOP切面编程能够在不修改源码的情况下,非常方便地实现系统监控、日志输出等功能,并且是独立的模块,利于维护。
当然AOP还有非常多的应用场景,本文仅做了访问日志基础应用示例,后续还需要不断探索实践。