手把手教你如何优雅的使用Aop记录带参数的复杂Web接口日志 (5)

将上面的所有的参数全部添加到Param类中,全部定义成字符串类型。

package spring.aop.log.demo.api.util; import lombok.Data; /** * Param * * @author Lunhao Hu * @date 2019-01-30 17:14 **/ @Data public class Param { /** * 所有可能参数 */ private String id; private String age; private String workOrderNumber; private String userId; private String name; private String email; } 修改模板

将WARNING模板修改如下。

/** * 操作类型 */ WARNING("警告", "因 工单号 [(%workOrderNumber)] /举报 ID [(%id)] 警告玩家 [(%userId)], 游戏名 [(%name)], 年龄 [(%age)]"); 修改controller @Log(type = "WARNING") @PostMapping("test/{id}") public String test( @PathVariable(name = "id") Integer id, @RequestParam(name = "workOrderNumber", required = false) String workOrderNumber, @RequestParam(name = "userId") String userId, @RequestBody TestDTO testDTO ) { return "Hello" + id; } 修改getRequestParam /** * 获取拦截的请求中的参数 * @param point */ private void getRequestParam() { // 获取简单参数类型 this.getSimpleParam(); // 获取复杂参数类型 this.getComplexParam(); }

接下来实现getComplexParam方法。

getComplexParam /** * 获取复杂参数类型的值 */ private void getComplexParam() { for (Object arg : this.args) { // 跳过简单类型的值 if (arg != null && !this.isBasicType(arg)) { this.getFieldsParam(arg); } } } getFieldsParam /** * 遍历一个复杂类型,获取值并赋值给param * @param target * @param <T> */ private <T> void getFieldsParam(T target) { Field[] fields = target.getClass().getDeclaredFields(); for (Field field : fields) { String paramName = field.getName(); if (this.isExist(paramName)) { String value = this.getParam(target, paramName); this.setParam(this.params, paramName, value); } } } 运行

启动项目。使用postman对上面的url发起POST请求。请求body中带上TestDTO中的参数。请求成功返回后就会看到控制台输出如下。

因 工单号 [空] /举报 ID [8] 警告玩家 [748327843], 游戏名 [tom], 年龄 [12]

然后就可以根据需求,将上面的日志记录到相应的地方。

到这可能有些哥们就觉得行了,万事具备,只欠东风。但其实这样的实现方式,还存在几个问题。

比如,如果请求失败了怎么办?请求失败,在需求上将,是根本不需要记录操作日志的,但是即使请求失败也会有返回值,就代表日志也会成功的记录。这就给后期查看日志带来了很大的困扰。

再比如,如果我需要的参数在返回值中怎么办?如果你没有用统一的生成唯一id的服务,就会遇到这个问题。就比如我需要往数据库中插入一条新的数据,我需要得到数据库自增id,而我们的日志拦截只拦截了请求中的参数。所以这就是我们接下来要解决的问题。

判断请求是否成功

实现success函数,代码如下。

/** * 根据http状态码判断请求是否成功 * * @param response * @return */ private Boolean success(HttpServletResponse response) { return response.getStatus() == 200; }

然后将getRequestParam之后的所有操作,包括getRequestParam本身,用success包裹起来。如下。

if (this.success(response)) { // 从请求传入参数中获取数据 this.getRequestParam(); if (!logDetail.isEmpty()) { // 将模板中的参数全部替换掉 logDetail = this.replaceParam(logDetail); } }

这样一来,就可以保证只有在请求成功的前提下,才会记录日志。

通过反射获取返回的参数 新建Result类

在一个项目中,我们用一个类来统一返回值。

package spring.aop.log.demo.api.util; import lombok.Data; /** * Result * * @author Lunhao Hu * @date 2019-02-01 16:47 **/ @Data public class Result { private Integer id; private String name; private Integer age; private String email; } 修改controller @Log(type = "WARNING") @PostMapping("test") public Result test( @RequestParam(name = "workOrderNumber", required = false) String workOrderNumber, @RequestParam(name = "userId") String userId, @RequestBody TestDTO testDTO ) { Result result = new Result(); result.setId(1); result.setAge(testDTO.getAge()); result.setName(testDTO.getName()); result.setEmail(testDTO.getEmail()); return result; } 运行

启动项目,发起POST请求会发现,返回值如下。

{ "id": 1, "name": "tom", "age": 12, "email": "test@test.com" }

而控制台的输出如下。

因 工单号 [39424] /举报 ID [空] 警告玩家 [748327843], 游戏名 [tom], 年龄 [12]

可以看到,id没有被获取到。所以我们还需要添加一个函数,从返回值中获取id的数据。

getResponseParam

在getRequestParam后,添加方法getResponseParam,直接调用之前写好的函数。代码如下。

/** * 从返回值从获取数据 */ private void getResponseParam(Object value) { this.getFieldsParam(value); } 运行

再次发起POST请求,可以发现控制台的输出如下。

因 工单号 [39424] /举报 ID [1] 警告玩家 [748327843], 游戏名 [tom], 年龄 [12]

一旦得到了这条信息,我们就可以把它记录到任何我们想记录的地方。

项目源码地址

想要参考源码的大佬请戳 ->这里<-

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyzpdg.html