接口注解注入方式,接口上的注解
在项目中,我们会需要获取接口的操作日志。比如获取接口的接口名、操作人,接口运行时间、所属的服务、接口的类型(增删改查)等等。初级的做法是在接口方法执行完后将这些操作记录存入库中,这段代码写在接口中,但是这样违反了设计原则中的单一职责原则。常用的做法是使用AOP来做,在运行时动态的插入日志记录的代码。这里我是用注解来做。
创建日志记录表
首先我们来创建日志记录表:
operation表
当然后编写实体类:
编写日志记录注解
我们先定义一个注解OperationLog
这个注解里面定义了几个参数:
“
opType:业务类型
opBusinessName:业务名称,例如会员服务、订单服务等等
opBusinessId:业务来源ID,一般为主键ID
”
定义业务类型类OperationType
这个业务类型类定义了接口的类型:增删改查。
接下来我们编写切面类OperationLogAspect
获取方法上面的注解:
Method method = ((MethodSignature) pjp.getSignature()).getMethod();//获取目标方法上面的注解OperationLog opLog = method.getAnnotation(OperationLog.class);
执行目标方法:
try { // 执行目标方法 result = pjp.proceed();} catch (Throwable throwable) { throw new Exception(throwable);}
在执行目标方法前后记录执行时间:
TimeInterval timer = DateUtil.timer();... // 执行目标方法...long executeTime = timer.intervalRestart();
解析注解上的表达式,就是获取业务id:
// 解析表达式,获取结果String itemId = String.valueOf(expression.getValue(context));
将数据封装到对象中:
Operation operation = Operation.builder() //.id(snowflake.nextId()) .opType(opLog.opType().name()) .opBusinessName(opLog.opBusinessName()) .opBusinessId(itemId) .opTime(String.valueOf(executeTime)) //这里可以添加操作人 .build();
记录日志并入库:
private void handle(Operation operation) { // 通过日志打印输出 log.info("opType = " + operation.getOpType() + ",opItem = " + operation.getOpBusinessName() + ",opItemId = " + operation.getOpBusinessId() + ",opTime = " + operation.getOpTime()); // 持久化入库 operationService.save(operation);}
整体代码如下:
测试注解
测试注解代码如下:
@RequestMapping("/getById")@ResponseBody@OperationLog(opType = OperationType.QUERY,opBusinessName = "会员服务",opBusinessId = "#id")public Member getById(@RequestParam String id) { return memberService.getById(id);}
我们在这个接口getById上添加了注解@OperationLog,表明我们想记录这个接口的操作记录。opType为查询类型,所属的业务为会员服务,业务id为接口的参数id。
启动代码运行接口:
控制台打印了日志:
并且数据库也有了记录:
代码到这里就结束了,当然我们还可以在日志记录表中添加接口名的路径、以及接口的调用链等信息。