1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 手放开 李圣杰
  4. 4 迷人的危险3(翻自 dance flow) FAFA
  5. 5 山楂树之恋 程佳佳
  6. 6 summertime cinnamons / evening cinema
  7. 7 不谓侠(Cover 萧忆情Alex) CRITTY
  8. 8 神武醉相思(翻自 优我女团) 双笙
  9. 9 空山新雨后 音阙诗听 / 锦零
  10. 10 Wonderful U (Demo Version) AGA
  11. 11 广寒宫 丸子呦
  12. 12 陪我看日出 回音哥
  13. 13 春夏秋冬的你 王宇良
  14. 14 世界が终わるまでは… WANDS
  15. 15 多想在平庸的生活拥抱你 隔壁老樊
  16. 16 千禧 徐秉龙
  17. 17 我的一个道姑朋友 双笙
  18. 18 大鱼  (Cover 周深) 双笙
  19. 19 霜雪千年(Cover 洛天依 / 乐正绫) 双笙 / 封茗囧菌
  20. 20 云烟成雨(翻自 房东的猫) 周玥
  21. 21 情深深雨濛濛 杨胖雨
  22. 22 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  23. 23 斑马斑马 房东的猫
  24. 24 See You Again Wiz Khalifa / Charlie Puth
  25. 25 Faded Alan Walker / Iselin Solheim
  26. 26 Natural J.Fla
  27. 27 New Soul Vox Angeli
  28. 28 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  29. 29 像鱼 王贰浪
  30. 30 Bye Bye Bye Lovestoned
  31. 31 Blame You 眠 / Lopu$
  32. 32 Believer J.Fla
  33. 33 书信 戴羽彤
  34. 34 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  35. 35 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  36. 36 慢慢喜欢你 LIve版(翻自 莫文蔚) 戴羽彤
  37. 37 病变(翻自 cubi) 戴羽彤
  38. 38 那女孩对我说 (完整版) Uu
  39. 39 绿色 陈雪凝
  40. 40 月牙湾 LIve版(翻自 F.I.R.) 戴羽彤
夜空中最亮的星(翻自 逃跑计划) - 戴羽彤
00:00 / 04:10

夜空中最亮的星 能否听清

那仰望的人 心底的孤独和叹息

夜空中最亮的星 能否记起

那曾与我同行 消失在风里的身影

我祈祷拥有一颗透明的心灵

和会流泪的眼睛

给我再去相信的勇气

越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请指引我靠近你

夜空中最亮的星 是否知道

那曾与我同行的身影 如今在哪里

夜空中最亮的星 是否在意

是等太阳先升起 还是意外先来临

我宁愿所有痛苦都留在心底

也不愿忘记你的眼睛

哦 给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行 哒~

我祈祷拥有一颗透明的心灵

和会流泪的眼睛 哦

给我再去相信的勇气

哦 越过谎言去拥抱你

每当我找不到存在的意义

每当我迷失在黑夜里

噢喔喔 夜空中最亮的星

请照亮我向前行

警告!前同事被移出公司技术群,原因竟然是……

老实交代,是不是要要多一点套路你才会点开看。《病变》哼起来:是不是要我多一些套路,才会让你点开看?好了,今天皮一下,大家周末快乐鸭🦆

今天我们讲的主题是门面日志,虽然有套路,既然点看来就看看吧!

起因

以前对日志的认知,只停留在能用就行,能够满足需求完美输出就行,但最近发现自己对日志的认知还是太过浅显,所以今天我要分享的就是如何更合理地使用日志,也是今天这篇博客的缘由。

最近项目在做组内培训,我想借着机会给大家推一下有关代码规范方面,主体内容是以阿里巴巴地《java开发手册(嵩山版)》进行的,在其中有关于日志的描述有这样的强制要求:

【强制】应用中不可直接使用日志系统(Log4jLogback) 中的 API ,而应依赖使用日志框架
(SLF4J、JCL--Jakarta Commons Logging) 中的 API ,使用门面模式的日志框架,有利于维护和
各个类的日志处理方式统一

说明:日志框架(SLF4J、JCL--Jakarta Commons Logging)的使用方式(推荐使用 SLF4J)

//使用 SLF4J:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Test.class);
//使用 JCL:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
private static final Log log = LogFactory.getLog(Test.class);

然后,我根据自己的以往的经验,查了一些资料,就明白了为什么有这样的强制规范要求,但这里我先卖个关子,最后再来说原因,接下来我们做一个demo实验。

实验走起

创建项目

这里为了更好地演示效果,创建的是普通地maven项目,项目结构如下:

log4J

我们先用log4j展开,具体步骤如下:

引入依赖

我们先引入log4j的依赖,版本无所谓:

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>

日志配置及示例

log4j的日志等级分为TRACE,DEBUG,INFO,WARN,ERRORFATAL,其中debug、info、warn、error我们经常用到,至于trace、fatal实话实说,我也没用过,很少接触。我个人理解是,如果你有比debug更详细的日志打印需求,那就采用trace,也就是要追踪更详细的问题,用trace,同样你有比error更粗略的日志记录需求,那可以采用fatal。

经过我的实验,log4j.properties文件只需要如下简单配置,就可以保证日志输出:

log4j.rootLogger=trace, out
log4j.appender.out = org.apache.log4j.ConsoleAppender

log4j.appender.out.layout = org.apache.log4j.PatternLayout
示例

但是上面这些配置只能保证日志输出,而且显示效果不友好,看看我的示例:

java测试代码
 public void log4jTest() {
        log4j.trace("log4j trace……");
        log4j.debug("log4j debug……");
        log4j.info("log4j info");
        log4j.warn("log4j warn……");
        log4j.error("log4j error……");
        log4j.fatal("log4j fatal……");
    }
输出示例
log4j trace……
log4j debug……
log4j info
log4j warn……
log4j error……
log4j fatal……

是不是极其不友好,现在我们加一个格式化配置:

log4j.appender.out.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
#log4j.appender.out.layout.ConversionPattern = %d{yyyy-MM-dd  HH:mm:ss} %5p (%F:%L) - %m%n
# 底下的配置当日志等级为trace的时候有问题,乱码

再运行,日志显示变得更友好了:

0    [main] TRACE io.github.syske.logger.LoggerTest  - log4j trace……
2    [main] DEBUG io.github.syske.logger.LoggerTest  - log4j debug……
2    [main] INFO  io.github.syske.logger.LoggerTest  - log4j info
2    [main] WARN  io.github.syske.logger.LoggerTest  - log4j warn……
2    [main] ERROR io.github.syske.logger.LoggerTest  - log4j error……
2    [main] FATAL io.github.syske.logger.LoggerTest  - log4j fatal……

因为今天重点不是将如何使用日志,所以log4j就讲到这里,我们继续看其他日志工具。

logback

引入依赖

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

日志配置及示例

java代码
public void logbackTest() {
    logback.trace("logback trace……");
    logback.debug("logback debug……");
    logback.info("logback info");
    logback.warn("logback warn……");
    logback.error("logback error……");
}

刚开始我的logback只这样初始化的:

ch.qos.logback.classic.Logger logback = new LoggerContext().getLogger(this.getClass());

刚开始想着通过logback单独输出日志,但发发现不行,压根走不通,不报错,但是日志无法输出,后来化成这样,日志就可以输出了:

// org.slf4j.Logger logback2 = new LoggerContext().getLogger(this.getClass()); 
// 上面这种写法也不行,不能输出,所以我就想不通为啥不让用logback直接输出日志(他不是强制使用日志门面吗,还是说就是我实验的这样,直接使用无法输出日志)
org.slf4j.Logger logback= LoggerFactory.getLogger(this.getClass());
配置
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
    </root>
<configuration>

反正我就想不通为啥不让用logback直接输出日志(他不是强制使用日志门面吗,还是说就是我实验的这样,直接使用无法输出日志。有知道具体原因的小伙伴欢迎留言讨论。

门面日志

为什么推荐使用门面日志

大家考虑这样的场景:如果你们的系统现阶段采用的是log4j进行日志管理,但后续因为业务变更,通过log4j无法满足新的业务需求,这时候要更换日志系统,你要怎么做?修改每个类吗?

就是基于这样的问题考量,门面日志才发挥了它的强大好处,能更好的满足我们的需求,保证我们程序再日志这块实现解耦。

那么什么是门面日志呢?

门面日志是什么

百度百科给的解释是:

简单日志门面,对应的英文为Simple Logging Facade,是存取日志的标准接口,包括slf4j、log4j、jdk logging api和apache common-log等具体实现。

我个人的理解是,门面日志就类似于一个日志接口,她不提供具体实现,但是会提供丰富的日志接口,让你可以自由选择自己的日志系统,甚至可以自己去实现相关接口。

目前常用的门面日志有slf4j和commons-logging,像log4j和logback就是完美地实现了这些门面日志的方法。

如何使用门面日志

门面日志的使用很简单,主要分为两步:

引入门面依赖

比如slf4j,只需要引入它的依赖包:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.30</version>
<dependency>

如果是commons-logging,一样引入它的依赖

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <version>1.2</version>
</dependency>

初始化日志对象

既然采用了门面日志,那么我们在初始化日志对象的时候就一定要采用门面日志,这样也方便日志管理,也就是我们前面我们提到的规范:

//使用 SLF4J:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Test.class);
//使用 JCL:
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
private static final Log log = LogFactory.getLog(Test.class);

引入具体的日志系统

完成上面的工作,你的项目日志就ok了,但是日志是不会输出的,这时候还需要你引入具体的日志实现,比如log4j,或者logback,如果是maven项目的话,logback会自动引入slf4j-api的依赖:

logback

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

或者log4j

<dependency>
    <groupId>log4j</groupId>
    <artifactId>log4j</artifactId>
    <version>1.2.12</version>
</dependency>

配置日志

这里很重要,你如果引入的是log4j作为日志实现的话,你就在配置文件中加入log4j的配置log4j.properties

log4j.rootLogger=trace, out
log4j.appender.out = org.apache.log4j.ConsoleAppender

log4j.appender.out.layout = org.apache.log4j.PatternLayout

如果你引入的是logback,那你就在配置文件中加入logback的配置logback.xml

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <!-- encoders are assigned the type
             ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
    </root>
<configuration>

如何切换日志系统

采用门面日志以后,日志的切换就变得很容易了,只需要替换具体的实现依赖,然后再变更相应的日志配置即可,至于代码,压根就不需要动。这也是我们为什么要采用门面日志的原因——降低日志系统的耦合性。

推荐使用slf4j

为什么推荐slf4j,其实是个小原因,就是她支持占位符输出,而commons-logging不支持。比如说我们需要输出这样的错误信息:

115  [main] ERROR io.github.syske.logger.LoggerTest - 错误信息:系统查询异常,错误原因:网络异常,错误类型:致命错误 
用slf4j
logback.error("错误信息:{},错误原因:{},错误类型:{}","系统查询异常","网络异常","致命错误");
用commons-logging
log.error("错误信息:" + "系统查询异常" +",错误原因:" + "网络异常" + ",错误类型:" + "致命错误");

你觉得哪个更友好呢?让我来选,毫不犹豫会选slf4j.

总结

今天其实没有讲太多的东西,核心说了一个问题,就是日常开发推荐使用门面日志。至于为什么推荐使用门面日志,就是为了更好地实现日志解耦。

最后,用我给我们项目组宣讲的时候的一段话结束今天的内容:

雪崩时,没有一片雪花是无辜的。同样的,系统宕机时,没有一行代码是无辜的,稳健的系统,优美的代码,离不开每一个人的努力,为了让整个项目更好,为了让每一个人都能成长受益,让我们一起努力……

当然这里要小改一下,我希望我们每个IT人写出的代码像诗一样优美,因为我一直觉得写程序本身也是创作,和写小说、写诗没有区别,唯一的区别是我们采用的语言不一样,而且我们创作的作品反而更有现实意义😂

posted @ 2020-09-05 14:30  云中志  阅读(192)  评论(0编辑  收藏  举报