使用spring的aop结合自定义注解实现操作日志的记录
首先引入依赖
<!--aop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
<!--工具类库-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.4</version>
</dependency>
自定义注解
import java.lang.annotation.*;
/**
* Created with IntelliJ IDEA.
* Description:
* Author: hsw
* Date: 2022/04/22/9:26
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestLog {
String methodName() ;
}
切面类
import cn.hutool.core.io.IoUtil;
import com.aiko.esdemo.annotation.RequestLog;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.log4j.Log4j2;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.nio.charset.Charset;
/**
* Created with IntelliJ IDEA.
* Description:
* Author: hsw
* Date: 2022/04/22/9:30
*/
@Aspect
@Component
@Log4j2
public class InterflowLogAspect {
//使用环绕通知,获取接口请求和返回参数
@Around("@annotation(com.aiko.esdemo.annotation.RequestLog)")
public void logAroundController(ProceedingJoinPoint pjp) {
//获取当前请求对象
//这个RequestContextHolder是Springmvc提供来获得请求的东西
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes)requestAttributes).getRequest();
//请求入参
String postData="";
try {
postData = IoUtil.read(request.getInputStream(), Charset.forName("UTF-8"));
} catch (IOException e) {
log.error( "##error found", e);
}
System.out.println("postData = " + postData);
//获取进入的类名
String className = pjp.getSignature().getDeclaringTypeName();
System.out.println("className = " + className);
// 获取方法签名
MethodSignature methodSignature = (MethodSignature) pjp.getSignature();
// 调用方法名称
String methodName = pjp.getSignature().getName();
System.out.println("methodName = " + methodName);
//获取方法上的注解
RequestLog reqLog = methodSignature.getMethod().getAnnotation(RequestLog.class);
System.out.println("reqLog = " + reqLog);
//请求方法中文名称
String reqMethodName = reqLog.methodName();
System.out.println("reqMethodName = " + reqMethodName);
// 请求的方法参数值
Object[] args = pjp.getArgs();
System.out.println("args = " + JSONObject.toJSONString(args));
String identity = (String) args[0];
System.out.println("identity = " + identity);
// 请求的方法参数名称
/*LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(methodSignature.getMethod());
System.out.println("paramNames = " + JSONObject.toJSONString(paramNames));*/
//获取返回对象
//接口返回msg
String msg="";
try {
JSONObject jsonResult = (JSONObject)pjp.proceed();
log.info(reqMethodName+"##jsonResult is {}", JSONObject.toJSONString(jsonResult));
msg=jsonResult.getString("Msg");
if (jsonResult.getInteger("SuccStat")==0){
msg="请求成功";
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
在controller的方法上添加自定义注解
@RequestMapping("/{identification}/queryToken")
@RequestLog(methodName = "获取token")
public Result helloWord(@PathVariable(name = "identification") String identification){
System.out.println("identification = " + identification);
return Result.ok(identification);
}
Result对象
package com.aiko.esdemo.dto;
import java.io.Serializable;
/**
* Created with IntelliJ IDEA.
* Description:
* Author: hsw
* Date: 2022/04/12/10:11
*/
public class Result<T> implements Serializable {
private static final long serialVersionUID = 6273326371984994386L;
private Integer code;
private String msg;
private T data;
private Result() {
this.code = 200;
this.msg = "OK";
}
private Result(T data) {
this.code = 200;
this.msg = "OK";
this.setData(data);
}
private Result(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
private Result(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public Result<T> setError(Integer code, String msg) {
this.setCode(code);
this.setMsg(msg);
return this;
}
public boolean isSuccess() {
return this.getCode().equals(200);
}
public static Result ok() {
return new Result();
}
public static <T> Result ok(T data) {
return new Result(data);
}
public static <T> Result ok(Integer code, String msg) {
return new Result(code, msg);
}
public static <T> Result ok(Integer code, String msg, T data) {
return new Result(code, msg, data);
}
public static <T> Result error() {
return new Result(500, "failed");
}
public static <T> Result error(String msg) {
return new Result(500, msg);
}
public static <T> Result error(Integer code, String msg) {
return new Result(code, msg);
}
public static <T> Result error(Integer code, String msg, T data) {
return new Result(code, msg, data);
}
public Integer getCode() {
return this.code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMsg() {
return this.msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return this.data;
}
public void setData(T data) {
this.data = data;
}
}
测试
postman测试(body可自定义,但必须是json格式)
aop打印
我这里是没有进行入库的,如果需要入库,只需要在切面类注入对应mapper接口,封装入库对象,执行insert就行