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

代码如下。

/** * 将数据写入参数类的实例中 * @param targetClass * @param key * @param value * @param <T> */ private <T> void setParam(T targetClass, String key, String value) { try { Method targetClassParamSetMethod = targetClass.getClass().getMethod("set" + this.setFirstLetterUpperCase(key), String.class); targetClassParamSetMethod.invoke(targetClass, value); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } }

该函数使用反射的方法,获取该参数的set方法,将Param类中对应的参数设置成传入的值。

运行

启动项目,并且请求controller中的方法。并且传入定义好的参数。

:8080/test/8?workOrderNumber=3231732&userId=748327843&name=testName

该GET请求总共传入了4个参数,分别是id,workOrderNumber,userId, name。大家可以看到,在Param类中并没有定义name这个字段。这是特意加了一个不需要记录的参数,来验证我们接口的健壮性的。

运行之后,可以看到控制台打印的信息如下。

Param(id=8, workOrderNumber=3231732, userId=748327843)

我们想让aop记录的参数全部记录到Param类中的实例中,而传入了意料之外的参数也没有让程序崩溃。接下里我们只需要将这些参数,将之前定义好的模板的参数预留字段替换掉即可。

替换参数

在doAfterReturning中的getRequestParam函数后,加入以下代码。

if (!logDetail.isEmpty()) { // 将模板中的参数全部替换掉 logDetail = this.replaceParam(logDetail); } System.out.println(logDetail);

下面我们实现replaceParam方法。

replaceParam

代码如下。

/** * 将模板中的预留字段全部替换为拦截到的参数 * @param template * @return */ private String replaceParam(String template) { // 将模板中的需要替换的参数转化成map Map<String, String> paramsMap = this.convertToMap(template); for (String key : paramsMap.keySet()) { template = template.replace("%" + key, paramsMap.get(key)).replace("(", "").replace(")", ""); } return template; }

convertToMap方法将模板中的所有预留字段全部提取出来,当作一个Map的Key。

convertToMap

代码如下。

/** * 将模板中的参数转换成map的key-value形式 * @param template * @return */ private Map<String, String> convertToMap(String template) { Map<String, String> map = new HashMap<>(); String[] arr = template.split("\\("); for (String s : arr) { if (s.contains("%")) { String key = s.substring(s.indexOf("%"), s.indexOf(")")).replace("%", "").replace(")", "").replace("-", "").replace("]", ""); String value = this.getParam(this.params, key); map.put(key, "null".equals(value) ? "(空)" : value); } } return map; }

其中的getParam方法,类似于setParam,也是利用反射的方法,通过传入的Class和Key,获取对应的值。

getParam

代码如下。

/** * 通过反射获取传入的类中对应key的值 * @param targetClass * @param key * @param <T> */ private <T> String getParam(T targetClass, String key) { String value = ""; try { Method targetClassParamGetMethod = targetClass.getClass().getMethod("get" + this.setFirstLetterUpperCase(key)); value = String.valueOf(targetClassParamGetMethod.invoke(targetClass)); } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } return value; } 再次运行

再次请求上述的url,则可以看到控制台的输出如下。

因 工单号 [3231732] /举报 ID [8] 警告玩家 [748327843]

可以看到,我们需要记录的所有的参数,都被正确的替换了。而不需要记录的参数,同样也没有对程序造成影响。

让我们试试传入不传入非必选参数,会是什么样。修改controller如下,把workOrderNumber改成非必须按参数。

@Log(type = "WARNING") @GetMapping("test/{id}") public String test( @PathVariable(name = "id") Integer id, @RequestParam(name = "workOrderNumber", required = false) String workOrderNumber, @RequestParam(name = "userId") String userId, @RequestParam(name = "name") String name ) { return "Hello" + id; }

请求如下url。

:8080/test/8?userId=748327843&name=testName

然后可以看到,控制台的输出如下。

因 工单号 [空] /举报 ID [8] 警告玩家 [748327843]

并不会影响程序的正常运行。

获取复杂参数类型

接下来要介绍的是如何记录复杂参数类型的日志。其实,大致的思路是不变的。我们看传入的类中的参数,有没有需要记录的。有的话就按照上面记录简单参数的方法来替换记录参数。

定义测试复杂类型

新建TestDTO。代码如下。

package spring.aop.log.demo.api.util; import lombok.Data; /** * TestDto * * @author Lunhao Hu * @date 2019-02-01 15:02 **/ @Data public class TestDTO { private String name; private Integer age; private String email; } 修改Param

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

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