1.自定义注解类
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface InterfaceSpLog {
/*
* 操作的页面(或模块)
* */
String operationName() default "";
/*
* 操作类型
* */
String operationType() default "";
/**
* 详细描述
*/
String description() default "";
}
该注解用在Controller方法上面,operationName和operationType可以根据业务需求定义枚举类,没定义枚举类的话就赋值具体内容。使用示例:
@PostMapping("api/v1/...")
@ResponseBody
@InterfaceSpLog(operationName = "1",operationType = "1",description = "...")
public Object FunctionName(@RequestBody TDtSyszb tDtSyszb) {
return xxService.xxFunction(tDtSyszb, false);
}
2.定义切面类
切面类用来处理日志内容。
前提知识讲解(个人粗鄙之见,有误请指正):
Controller方法:相当于切点(PointCut)
@Before前置通知:切点前的操作,通常只有登出操作为在before中记录日志
@Around环绕通知:供切入点使用,通常用来记录执行时间
@After后置通知:切点之后的操作,一般的用户操作都记录在这里,即controller方法执行完之后记录日志
@AfterReturning 可以获取到controller方法的返回值,方便有特殊业务要求的日志拼接
下面是示例代码,重点看@AfterReturning
@Aspect
@Component
@Slf4j
public class InterfaceSpLogAspect {
//注入保存日志的工具类————这是我司封装好的工具类。
//读者如果想把日志记录到数据库,可以注入相应的Mapper
@Autowired
private AuditLogUtil auditLogUtil;
/*
* 切点
* */
@Pointcut("@annotation(com.路径....InterfaceSpLog)")
public void interfaceAspect(){
}
/**
*Before
*/
@Before("interfaceAspect()")
public void doBefore(JoinPoint joinPoint){
}
//记录执行时间(没有也行)
@Around("interfaceAspect()")
public Object doAround(JoinPoint joinPoint){
log.info("=================执行AOP环绕通知==================");
long start = System.currentTimeMillis();
Object obj = "";
try {
obj = ((ProceedingJoinPoint) joinPoint).proceed();
long end = System.currentTimeMillis();
if (logger.isInfoEnabled()) {
logger.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
}
log.info("==============结束执行AOP环绕通知==================");
} catch (Throwable e) {
long end = System.currentTimeMillis();
if (logger.isInfoEnabled()) {
logger.error("around " + joinPoint + "\tUse time : " + (end - start) + " ms", e);
}
}
return obj;
}
@AfterReturning(returning = "returnData",pointcut ="interfaceAspect()")
public boolean doAfter(JoinPoint joinPoint,Object returnData) throws IllegalAccessException {
//从注解中获取到相关变量值
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
//通过这几个变量判断当前是哪个模块在进行哪种操作(有需要的话,方法参数和返回值也可以参与判断)
String operationName = method.getAnnotation(InterfaceSpLog.class).operationName();
String operationType = method.getAnnotation(InterfaceSpLog.class).operationType();
String description = method.getAnnotation(InterfaceSpLog.class).description();
//通过反射获取当前被拦截的Controller方法的参数,returnData是当前方法的返回值,二者注意区分
Object[] objects = joinPoint.getArgs();
StringBuilder sb = new StringBuilder(); //sb用来拼接日志
......//具体的拼接日志过程,如果有很多分类的话,可以使用Switch分情况,每种情况抽成一个方法,防止这个方法代码太臃肿
......//最后,把拼接的日志插入到数据库
}