Logback日志格式优化,解决输出***@2b193f2d问题

原文出处:Java之道

原文地址:http://www.hollischuang.com/archives/3689

 

  我们在开发的时候,经常要打印日志,有的时候会在一些代码的关键节点处进行日志输出。使用logback/log4j等原生的日志框架,在日志输出的时候可能会遇到一个问题,那就是经常我们要打印对象的时候,如以下代码:

log.info("req = {}", aRequest);

  打印结果却是以下形式:

req = com.hollis.java.ways.ApplyRequest@39ddf169

  其实原因比较简单,那就是要打印的对象没有重写toString方法,这样无法将该对象的参数打印出来。

  所以,为了可以把对象的值都打印出来,我们一般要求对于自己定义的入参、出参等定义toString方法。但是有些时候,我们使用的是外部定义的request和response对象,他们并没有覆盖toString,当对这些对象打印的时候,就会出现以上问题。

  一般简单的解决办法是,可以通过JSON把对象转成String,如:

log.info("req = {}", JSON.toJSONString(aRequest));

  日志输出:

req = {"name":"Hollis","wechat":"hollischuang","javaways":"Java之道"}

  但是,这样的话,就需要在每一个日志记录的地方人为的要处理下,很不高效,而且也容易遗忘。作为程序员,要想办法干掉这种手动操作,有一个好的办法,可以一劳永逸:借助logback(log4j也有类似的功能)的MessageConverter。无侵入性的解决这个问题

  

  1. 定义一个MessageConverter

public class ArgumentJsonFormatLayout extends MessageConverter {

    @Override
    public String convert(ILoggingEvent event) {
        try {
            return MessageFormatter.arrayFormat(event.getMessage(), Stream.of(event.getArgumentArray())
                .map(JSON::toJSONString).toArray()).getMessage();
        } catch (Exception e) {
            return event.getMessage();
        }
    }
}

  上面这段代码,会把所有的需要打印的内容全部JSON格式化,但如果遇到已经格式化的JSON,或者String类型的内容,打印日志时,会多一层双引号,所以下面做了优化。

public class LogJsonConverter extends MessageConverter {

    @Override
    public String convert(ILoggingEvent event) {
        try {
            Object[] objects = Stream.of(event.getArgumentArray()).map(t -> {
                String str;
                if (t instanceof String) {
                    // String类型直接打印
                    str = t.toString();
                } else {
                    str = JSON.toJSONString(t);
                }
                return str;
            }).toArray();
            return MessageFormatter.arrayFormat(event.getMessage(), objects).getMessage();
        } catch (Exception e) {
            return event.getMessage();
        }
    }

}

 

  2. 在logback的配置文件中加上配置上这个类

<configuration>
    ……
    <conversionRule conversionWord="m" converterClass="com.ha.java.ways.ArgumentJsonFormatLayout"/>
    ……
</configuration>  

  注意:conversionWord里的值m不是随便写的,要和logback里的日志输出格式里的信息参数相同。比如:

[%-5level] [%d{yyyy-MM-dd HH:mm:ss.SSS}] [%t] [%logger.%method:%line] -- %m%n

 

 

补充:我在查阅网上资料时,发现很多金融、电商项目会用这个类实现对用户名、密码、交易密码等信息的脱敏处理,也很方便,不过实现逻辑比较复杂,大家可以自己查阅。

补充资料:

https://www.jianshu.com/p/ade8b7c220df

https://blog.csdn.net/fywfengyanwei/article/details/78484590

 

posted @ 2019-12-04 16:25  闲人鹤  阅读(1190)  评论(0编辑  收藏  举报