只是做一个简单的日志记录,比如某个url进入哪个controller并将参数输出。
1、首先在pom.xml中导入aop的包
<!--aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 利用fastjson转json打印 建议使用1.2.61版本及以上,否则有漏洞-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.61</version>
</dependency>
2、新建一个java类
/**
* 系统日志:切面处理类
*/
@Aspect
@Component
public class SysLogAspect {
private final static Logger logger = LoggerFactory.getLogger(SysLogAspect.class);
//定义需要进行切面的路径
private final String path = "execution(public * com.test.controller..*.*(..))";
/**
* 定义一个切入点.
*/
@Pointcut(path)
public void logPoinCut(){
}
//切面 配置通知
@Before("logPoinCut()")
public void saveSysLog(JoinPoint joinPoint) {
ServletRequestAttributes attributes = (ServletRequestAttributes)
RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
//获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
//获取请求的方法名
String methodName = method.getName();
map.put("method",className + "." + methodName);
//将参数所在的数组转换成json
String params = JSON.toJSONString(request.getParameterMap(), SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.WriteMapNullValue);
map.put("params",param);
logger.info(map.toString());
}
}
上面即可完成一个简单的aop切面做日志记录。
几天后,线上发现数据问题,我进行查看日志,突然发现好多参数没有打印,查看同事代码发现,由于参数较多,前端的时候封装成了json对象传到后台,后台的同事用@RequestBody注解进行接收,导致参数不能正常打印。我又对上面的代码进行了优化。
/**
* @program: ucar
* @description: 对日志进行切面记录
* @author: zhao
* @create: 2019-12-19 09:58
*/
@Aspect
@Component
public class SystemLogAspect {
private final static Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);
//定义切点路径
private final String path = "execution(public * com.broad.research.ucar.wechat.controller..*.*(..))";
/**
* 定义一个切入点.
*/
@Pointcut(path)
public void logPoinCut(){
}
//切面 配置通知
@Before("logPoinCut()")
public void sysLog(JoinPoint joinPoint) {
//保存日志
Map map = new HashMap();
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
HttpServletResponse response = attributes.getResponse();
//从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
//获取请求的类名
String className = joinPoint.getTarget().getClass().getName();
// joinPoint获取参数名
String[] params = ((CodeSignature) joinPoint.getStaticPart().getSignature()).getParameterNames();
//获取请求的方法名
String methodName = method.getName();
map.put("method",className + "." + methodName);
// joinPoint获取参数值
Object[] args = joinPoint.getArgs();
StringBuffer logStr = new StringBuffer();
int i = 0;
for (Object arg : args) {
if (arg == request || arg == response) {
i+=1;
continue;
}
if(logStr.length()>0){
logStr.append("&"+params[i]+"="+arg);
}else{
logStr.append(params[i]+"="+arg);
}
i+=1;
}
//将参数所在的数组转换成json
String param = JSON.toJSONString(request.getParameterMap(), SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.WriteMapNullValue);
map.put("json",logStr); //@RequestBody注解传递参数
map.put("params",param); //正常request.getParameter
logger.info(map.toString());
}
/**
* 后置返回通知
* @AfterReturning注解用于获取方法的返回值
* @param object
*/
@AfterReturning(pointcut = "logPoinCut()", returning = "object")
public void getAfterReturn(Object object) {
logger.info("aop return:{}", JSONObject.toJSONString(object));
}
}