忽略日志吃大亏,手把手教你玩转 SpringBoot 日志
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">1、</span>日志重要吗</span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">程序中的日志重要吗? 在回答这个问题前,笔者先说个事例:</p><span style="color: black;">❝</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">笔者印象尤深的<span style="color: black;">便是</span>去年某个同事,收到了客户反馈的紧急bug。尽管申请到了日志文件,但<span style="color: black;">由于</span><span style="color: black;">非常多</span>关键<span style="color: black;">过程</span><span style="color: black;">无</span>打印日志,<span style="color: black;">引起</span>排查进度很慢,数个小时都没能排查到问题,<span style="color: black;">亦</span><span style="color: black;">没法</span>给出<span style="color: black;">处理</span>对策。<span style="color: black;">引起</span>了客户程序<span style="color: black;">始终</span>阻断,<span style="color: black;">最后</span>产生了不少损失。
事后,经过仔细推敲,成功复现了这个bug,其实是一个很不起眼的数据转换<span style="color: black;">引起</span>的。可<span style="color: black;">由于</span>日志内容的匮乏,排查起来难度很大。其实只要在数据转换前后进行日志输出,这个问题<span style="color: black;">便是</span>一眼的事。但可惜没<span style="color: black;">倘若</span>,故事的最后,<span style="color: black;">研发</span><span style="color: black;">分部</span>还是遭到了客户的投诉,影响到了<span style="color: black;">分部</span>绩效</p><span style="color: black;">❞</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">针对</span>刚学习编程的<span style="color: black;">朋友</span>,<span style="color: black;">非常多</span>人都对日志满不在乎,<span style="color: black;">咱们</span>在做code review的时候,经常<span style="color: black;">发掘</span><span style="color: black;">有些</span>新<span style="color: black;">朋友</span><span style="color: black;">爱好</span>一个<span style="color: black;">办法</span>写得很长,<span style="color: black;">而后</span>中间的注释和日志都少的可怜。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">坦白的说,这是很<span style="color: black;">欠好</span>的习惯,这<span style="color: black;">寓意</span>着日后<span style="color: black;">办法</span>出了bug,<span style="color: black;">或</span>需要迭代,要花费<span style="color: black;">海量</span>时间来理清<span style="color: black;">办法</span>的思路。千万别迷信什么“<span style="color: black;">办法</span>名、字段名起的见明知意,就<span style="color: black;">能够</span>不写注释与日志”,那是<span style="color: black;">她们</span>的业务场景<span style="color: black;">不足</span><span style="color: black;">繁杂</span>。以笔者为例,<span style="color: black;">繁杂</span>的场景<span style="color: black;">触及</span><span style="color: black;">非常多</span>公式、奇特的规定,不写注释与日志,后续没人能<span style="color: black;">守护</span>得了</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因此</span>请务必记住,日志在<span style="color: black;">研发</span>过程中非常重要。它<span style="color: black;">能够</span><span style="color: black;">帮忙</span><span style="color: black;">研发</span>人员<span style="color: black;">认识</span>程序中<span style="color: black;">出现</span>了什么,以及在某些<span style="color: black;">状况</span>下<span style="color: black;">为何</span>会<span style="color: black;">出现</span>错误或<span style="color: black;">反常</span>。<span style="color: black;">经过</span>查看日志,<span style="color: black;">研发</span>人员<span style="color: black;">能够</span><span style="color: black;">容易</span>地定位并<span style="color: black;">处理</span>问题,并且<span style="color: black;">能够</span>更好地监控和<span style="color: black;">调节</span>应用程序的性能,在必要时进行故障排除和安全<span style="color: black;">检测</span></p><img src="https://mmbiz.qpic.cn/mmbiz_png/eQPyBffYbucUibY4lxlxBZRgyPiciaiaOA9o4elcabQE5P2Mk8Zp8mKxCB9Z06XXsJvrHBCT1Zc7ibDbSbH0RGEHg7Q/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">2、</span>日志分级</span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">最<span style="color: black;">起始</span>的日志分级<span style="color: black;">是由于</span>Syslog的<span style="color: black;">研发</span>者Eric Allman在1981年提出的。之后,这个级别分级系统被广泛应用于<span style="color: black;">各样</span><span style="color: black;">行业</span>的日志记录和信息处理中。下面<span style="color: black;">咱们</span>就来介绍下常用的日志等级</p>TRACE<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">是最低级别的日志记录,用于输出最<span style="color: black;">仔细</span>的调试信息,<span style="color: black;">一般</span>用于<span style="color: black;">研发</span>调试目的。在生产环境中,应该关闭 TRACE 级别的日志记录,以避免输出<span style="color: black;">太多</span>无用信息。</p>DEBUG<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">是用于输出程序中的<span style="color: black;">有些</span>调试信息,<span style="color: black;">一般</span>用于<span style="color: black;">研发</span>过程中。像 TRACE <span style="color: black;">同样</span>,在生产环境中应该关闭 DEBUG 级别的日志记录。</p>INFO<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">用于输出程序正常运行时的<span style="color: black;">有些</span>关键信息,<span style="color: black;">例如</span>程序的<span style="color: black;">起步</span>、运行日志等。<span style="color: black;">一般</span>在生产环境中开启 INFO 级别的日志记录。</p>WARN<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">是用于输出<span style="color: black;">有些</span>警告信息,提示程序可能会<span style="color: black;">显现</span><span style="color: black;">有些</span><span style="color: black;">反常</span><span style="color: black;">或</span>错误。在应用程序中,WARN 级别的日志记录<span style="color: black;">一般</span>用于记录<span style="color: black;">有些</span>非致命性<span style="color: black;">反常</span>信息,以便能够<span style="color: black;">即时</span><span style="color: black;">发掘</span>并处理这些问题。</p>ERROR<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">是用于输出程序运行时的<span style="color: black;">有些</span>错误信息,<span style="color: black;">一般</span><span style="color: black;">暗示</span>程序<span style="color: black;">显现</span>了<span style="color: black;">有些</span>不可预料的错误。在应用程序中,ERROR 级别的日志记录<span style="color: black;">一般</span>用于记录<span style="color: black;">有些</span>致命性的<span style="color: black;">反常</span>信息,以便能够<span style="color: black;">即时</span><span style="color: black;">发掘</span>并处理这些问题。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">当然,除了这五种级别以外,还有<span style="color: black;">有些</span>日志框架定义了其他级别,例如 Python 中的 CRITICAL、PHP 中的 FATAL 等。CRITICAL 和 FATAL 都是用于<span style="color: black;">暗示</span>程序<span style="color: black;">显现</span>了致命性错误<span style="color: black;">或</span><span style="color: black;">反常</span>,即不可恢复的错误。当然,<span style="color: black;">针对</span><span style="color: black;">咱们</span>今天要说的内容,<span style="color: black;">晓得</span><span style="color: black;">以上</span>五种日志等级就够了。</p>
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">3、</span>常用日志插件</span></h3>Log4j(1999年诞生)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Log4j 是Java<span style="color: black;">行业</span>中最早的流行日志框架之一。它由Ceki Gülcü<span style="color: black;">研发</span>,并后来由Apache软件基金会接管。Log4j <span style="color: black;">供给</span>了灵活的配置选项、多种输出目的地、日志级别和分层日志体系。尽管Log4j 1在其时代取得了巨大的成功,但在性能和某些功能方面存在限制,<span style="color: black;">因此呢</span>后来演化为Log4j 2。</p>SLF4J(2004年诞生)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">严格<span style="color: black;">来讲</span>,SLF4J(Simple Logging Facade for Java)并不算一个插件,而是Ceki Gülcü<span style="color: black;">研发</span>的一个日志门面接口。它为Java应用程序<span style="color: black;">供给</span>了统一的日志抽象,使<span style="color: black;">研发</span>人员<span style="color: black;">能够</span><span style="color: black;">运用</span>一致的API进行日志记录,而不需要直接依赖于特定的日志实现。SLF4J <span style="color: black;">能够</span>与多种底层日志框架(如Logback、Log4j 2、java.util.logging等)结合<span style="color: black;">运用</span>。</p>Logback(2009年诞生)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Logback 是Ceki Gülcü<span style="color: black;">研发</span>的日志框架,他<span style="color: black;">亦</span>是Log4j的作者。Logback 是Log4j 1的后续版本,旨在<span style="color: black;">供给</span>更高性能、更灵活的配置和现代化的日志<span style="color: black;">处理</span><span style="color: black;">方法</span>。Logback 支持异步日志记录、多种输出格式、灵活的配置以及与SLF4J紧密集成。</p>Log4j 2(2014年诞生)<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Log4j 2 是Apache软件基金会<span style="color: black;">研发</span>的Log4j的下一代版本。它引入了许多新特性,如异步日志记录、插件支持、丰富的过滤器等,旨在<span style="color: black;">供给</span>更好的性能和灵活性。Log4j 2 在设计上<span style="color: black;">思虑</span>了Log4j 1的局限性,并且支持多种配置方式。</p>小故事<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">不难<span style="color: black;">重视</span>到,一个有意思的小故事是,前三款日志插件都是Ceki Gülcü<span style="color: black;">研发</span>的,但 Log4j 2 并不是,虽然<span style="color: black;">此刻</span>有<span style="color: black;">非常多</span>人以为log4j2<span style="color: black;">亦</span>是他写的,但<span style="color: black;">咱们</span>在github上<span style="color: black;">能够</span>看到其个人说明 “Unaffiliated with log4j 2.x.” (与 log4j 2.x 无关),<span style="color: black;">因此</span>log4j2 和 logback 都自<span style="color: black;">叫作</span>是log4j 的后续版本,到底谁才算正统续作呢?这就留给各位读者自己玩味了</p><img src="https://mmbiz.qpic.cn/mmbiz_png/eQPyBffYbucUibY4lxlxBZRgyPiciaiaOA9o7a9ZxGyNUa02krchyN29iceR9oqHqfzDtOtMduY5CKrUe3gUhCUiaApw/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">4、</span>外观模式与SLF4J</span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在讲解<span style="color: black;">更加多</span>插件详情之前,<span style="color: black;">咱们</span>先来<span style="color: black;">瞧瞧</span><span style="color: black;">运用</span>最多的SLF4J ,<span style="color: black;">咱们</span>前面说了 SLF4J(Simple Logging Facade for Java)是Ceki Gülcü<span style="color: black;">研发</span>的一个日志门面接口,<span style="color: black;">那样</span>很显然<span style="color: black;">这儿</span>就用到了门面模式(即Facade 或 外观模式),笔者比较习惯说成是外观模式,后续就<span style="color: black;">叫作</span>为外观模式。</p><img src="https://mmbiz.qpic.cn/mmbiz_png/eQPyBffYbucUibY4lxlxBZRgyPiciaiaOA9o3HDAAlbHeX4aFUjDnL4I72VJY6hvMrQODm1YDiacB2NZIRDoE1osYPQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;"><span style="color: black;">1. 外观模式</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">定义:外观模式是一种结构型设计模式,它<span style="color: black;">供给</span>了一个简单的接口,封装了底层<span style="color: black;">繁杂</span>的子系统,使得客户端<span style="color: black;">能够</span>更方便地<span style="color: black;">运用</span>这个子系统</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">目的:外观模式的目的是<span style="color: black;">隐匿</span>底层系统的<span style="color: black;">繁杂</span>性,降低<span style="color: black;">拜访</span>成本。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span>说看定义有些抽象,那<span style="color: black;">咱们</span><span style="color: black;">能够</span>以生活中的例子<span style="color: black;">来讲</span>,<span style="color: black;">咱们</span>都知道<span style="color: black;">此刻</span>越来越流行智能家居,<span style="color: black;">亦</span><span style="color: black;">便是</span>家庭内装了<span style="color: black;">非常多</span>智能家电,从电视、空调、到廊灯<span style="color: black;">乃至</span>窗帘都是智能的。这类家庭<span style="color: black;">常常</span>会有一个<span style="color: black;">掌控</span>中心,<span style="color: black;">咱们</span>不需要手动去开电视,只需要对着<span style="color: black;">掌控</span>中心说:“小A小A,帮我打开电视,音量调到30%”,电视就会应声打开并调节音量</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">那样</span><span style="color: black;">这般</span>的话,<span style="color: black;">咱们</span>不需要<span style="color: black;">晓得</span>怎么开电视,怎么调音量。通通都能用最简单的话语来调节。同理,<span style="color: black;">此刻</span>手机上的拍照功能:感光度,对焦,白平衡这些细节都给你自动完<span style="color: black;">成为了</span>,<span style="color: black;">因此</span>这些<span style="color: black;">繁杂</span>的内容你<span style="color: black;">此刻</span><span style="color: black;">基本</span><span style="color: black;">不消</span>管,只需要猛按拍照键<span style="color: black;">就可</span>。</p><img src="https://mmbiz.qpic.cn/mmbiz_png/eQPyBffYbucUibY4lxlxBZRgyPiciaiaOA9oJxM7vWayVQ9Hxmdwh3x80k0PR85Bf9JGHGtWOYju88ibefhEbRrkxTQ/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">这<span style="color: black;">便是</span>外观模式的<span style="color: black;">道理</span>,<span style="color: black;">外观模式<span style="color: black;">便是</span>为了<span style="color: black;">隐匿</span>系统的<span style="color: black;">繁杂</span>性而设计出来的,让客户端只对接触到一个外观类,而不会接触到系统内部的<span style="color: black;">繁杂</span><span style="color: black;">规律</span></span></p><span style="color: black;">2. SLF4J 的诞生</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在<span style="color: black;">初期</span><span style="color: black;">运用</span>日志框架时,应用程序<span style="color: black;">一般</span>需要直接与<span style="color: black;">详细</span>的日志框架进行耦合,这就<span style="color: black;">引起</span>了以下几个问题:</p>代码依赖性<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">应用程序需要直接引用<span style="color: black;">详细</span>的日志框架,从而<span style="color: black;">引起</span>代码与日志框架强耦合,难以满足应用程序对日志框架的灵活配置。</p>日志框架不统一<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在<span style="color: black;">运用</span><span style="color: black;">区别</span>的日志框架时,应用程序需要<span style="color: black;">按照</span><span style="color: black;">详细</span>的日志框架来编写代码,这不仅会<span style="color: black;">增多</span><span style="color: black;">研发</span>难度,<span style="color: black;">况且</span>在多种日志框架中切换时需要进行<span style="color: black;">海量</span>的代码改动。</p>性能问题<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在日志输出频繁的<span style="color: black;">状况</span>下,<span style="color: black;">因为</span>日志框架的实现方式和API设计<span style="color: black;">区别</span>,可能会<span style="color: black;">引起</span>性能问题。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">为<span style="color: black;">认识</span>决这些问题,SLF4J<span style="color: black;">供给</span>了一套通用的日志门面接口,让应用程序<span style="color: black;">能够</span><span style="color: black;">经过</span>这些接口来记录日志信息,而不需要直接引用<span style="color: black;">详细</span>的日志框架。<span style="color: black;">这般</span>,应用程序就<span style="color: black;">能够</span>在<span style="color: black;">区别</span>的日志框架之间进行灵活配置和切换,<span style="color: black;">同期</span>还<span style="color: black;">能够</span><span style="color: black;">得到</span>更好的性能表现。<span style="color: black;">因此</span>,我<span style="color: black;">剧烈</span><span style="color: black;">意见</span>各位<span style="color: black;">运用</span>SLF4J, 而不是直接对接某个<span style="color: black;">详细</span>的日志框架。</p><span style="color: black;">3. SLF4J 的<span style="color: black;">运用</span></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">首要</span>,<span style="color: black;">咱们</span>需要在工程内引入包,<span style="color: black;">然则</span><span style="color: black;">倘若</span>你用了springboot,<span style="color: black;">各样</span> spring-boot-starter <span style="color: black;">起步</span>器<span style="color: black;">已然</span>引用过了,<span style="color: black;">因此</span>引用前最好确认下:</p><span style="color: black;"><<span style="color: black;">dependency</span>></span> <span style="color: black;"><<span style="color: black;">groupId</span>></span>org.slf4j<span style="color: black;"></<span style="color: black;">groupId</span>></span> <span style="color: black;"><<span style="color: black;">artifactId</span>></span>slf4j-api<span style="color: black;"></<span style="color: black;">artifactId</span>></span> <span style="color: black;"><<span style="color: black;">version</span>></span>1.7.32<span style="color: black;"></<span style="color: black;">version</span>></span><span style="color: black;"></<span style="color: black;">dependency</span>></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">而后</span>在<span style="color: black;">咱们</span>要打印日志的类里加上一行 ;private static final Logger logger = LoggerFactory.getLogger(XXXX.class); <span style="color: black;">就可</span><span style="color: black;">运用</span>,如下:</p><span style="color: black;">import</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> org.slf4j.Logger;</p><span style="color: black;">import</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> org.slf4j.LoggerFactory;</p><span style="color: black;">public</span> <span style="color: black;"><span style="color: black;">class</span> <span style="color: black;">MyClass</span> </span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{</p> <span style="color: black;">private</span> <span style="color: black;">static</span> <span style="color: black;">final</span> Logger log = LoggerFactory.getLogger(MyClass<span style="color: black;">.<span style="color: black;">class</span>)</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p> <span style="color: black;">//...</span> <span style="color: black;"><span style="color: black;">public</span> <span style="color: black;">static</span> <span style="color: black;">void</span> <span style="color: black;">main</span><span style="color: black;">(String[] args)</span> </span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{</p> log.info(<span style="color: black;">"This is an info message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">倘若</span><span style="color: black;">咱们</span>引用了lombok的话,<span style="color: black;">亦</span><span style="color: black;">能够</span><span style="color: black;">运用</span>lombok的注解@Slf4j 代替上面那句话来<span style="color: black;">运用</span> SLF4J ,如下:</p><span style="color: black;">import</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> lombok.extern.slf4j.Slf4j;</p><span style="color: black;">@Slf</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">4j</p><span style="color: black;">public</span> <span style="color: black;"><span style="color: black;">class</span> <span style="color: black;">MyClass</span> </span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{</p> <span style="color: black;"><span style="color: black;">public</span> <span style="color: black;">static</span> <span style="color: black;">void</span> <span style="color: black;">main</span><span style="color: black;">(String[] args)</span> </span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{</p> log.info(<span style="color: black;">"This is an info message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">然则</span>,<span style="color: black;">咱们</span>都<span style="color: black;">晓得</span>SLF4J仅仅是个门面,换句话说,仅有接口而<span style="color: black;">无</span>实现,<span style="color: black;">倘若</span>此刻<span style="color: black;">咱们</span>直接运行,打印日志是<span style="color: black;">无</span>用处的</p><img src="https://mmbiz.qpic.cn/mmbiz_png/eQPyBffYbucUibY4lxlxBZRgyPiciaiaOA9oInORLNiaH8ckzcickWQWmYnnw884tAfv6HciaZwOalTdX4oOV90BUnZxg/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因此</span>,<span style="color: black;">咱们</span><span style="color: black;">倘若</span>要运行,<span style="color: black;">咱们</span>必须要给 SLF4J 安排上实现,而<span style="color: black;">日前</span>最常用的<span style="color: black;">便是</span> logback 和 log4j2 了,就让<span style="color: black;">咱们</span>接着往下看</p>
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;"><span style="color: black;">5、</span>双雄之争</span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">其实关于 Logback 和 Log4j 2,网络上有<span style="color: black;">非常多</span>评测,就不需赘述了,<span style="color: black;">重点</span>是围绕性能方面的,从<span style="color: black;">日前</span><span style="color: black;">大众</span>的反馈看,Log4j 2 晚<span style="color: black;">显现</span>好几年,还是有后发<span style="color: black;">优良</span>的,性能会比 Logback 好。当然, Logback 本身性能<span style="color: black;">亦</span>很强,<span style="color: black;">针对</span>大<span style="color: black;">都数</span>场景,完全是够用的,<span style="color: black;">况且</span>配置比较直观,是spring-boot 默认<span style="color: black;">运用</span>的日志插件。</p><img src="https://mmbiz.qpic.cn/mmbiz_png/eQPyBffYbucUibY4lxlxBZRgyPiciaiaOA9oU0eyzpJkgauZ1pX4RHNRfaCicmlTcm3HHBgjYkABSibhPmpAlhx15cpA/640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=1&wx_co=1" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因此</span>,选谁都<span style="color: black;">能够</span>,<span style="color: black;">倘若</span>不想费神,<span style="color: black;">能够</span>直接<span style="color: black;">运用</span>spring-boot自带的Logback,<span style="color: black;">倘若</span>对日志性能<span style="color: black;">需求</span>很高,<span style="color: black;">运用</span>log4j2更保险,<span style="color: black;">咱们</span>接下来分别介绍两者。</p><span style="color: black;">1. Logback</span>1. 引用<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因为</span> Logback 为 spring-boot 默认日志框架,<span style="color: black;">因此</span>无需再引用,但<span style="color: black;">针对</span>非spring - boot 项目,<span style="color: black;">能够</span>做如下引用</p><span style="color: black;"><<span style="color: black;">dependency</span>></span> <span style="color: black;"><<span style="color: black;">groupId</span>></span>ch.qos.logback<span style="color: black;"></<span style="color: black;">groupId</span>></span> <span style="color: black;"><<span style="color: black;">artifactId</span>></span>logback-classic<span style="color: black;"></<span style="color: black;">artifactId</span>></span> <span style="color: black;"><<span style="color: black;">version</span>></span>1.2.12<span style="color: black;"></<span style="color: black;">version</span>></span><span style="color: black;"></<span style="color: black;">dependency</span>></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Logback 的核心模块为 logback-classic,它<span style="color: black;">供给</span>了一个 SLF4J 的实现,兼容 Log4j API,<span style="color: black;">能够</span>无缝地替换 Log4j。它<span style="color: black;">自己</span><span style="color: black;">已然</span><span style="color: black;">包括</span>了 logback-core 模块,而 logback-core,顾名思义<span style="color: black;">便是</span> logback 的核心功能,<span style="color: black;">包含</span>日志记录器、Appender、Layout 等。其他 logback 模块都依赖于该模块</p>2. 配置<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">logback <span style="color: black;">能够</span><span style="color: black;">经过</span> XML <span style="color: black;">或</span> Groovy 配置。下面以 XML 配置为例。logback 的 XML 配置文件名<span style="color: black;">叫作</span><span style="color: black;">一般</span>为 logback.xml <span style="color: black;">或</span> logback-spring.xml(在 Spring Boot 中),需要<span style="color: black;">安置</span>在 classpath 的根目录下,</p><span style="color: black;"><?xml version="1.0" encoding="UTF-8"?></span><span style="color: black;"><<span style="color: black;">configuration</span>></span> <span style="color: black;"><!--定义日志文件的存储<span style="color: black;">位置</span>,<span style="color: black;">运用</span>Spring的属性文件配置方式--></span> <span style="color: black;"><<span style="color: black;">springProperty</span> <span style="color: black;">scope</span>=<span style="color: black;">"context"</span> <span style="color: black;">name</span>=<span style="color: black;">"log.home"</span> <span style="color: black;">source</span>=<span style="color: black;">"log.home"</span> <span style="color: black;">defaultValue</span>=<span style="color: black;">"logs"</span>/></span> <span style="color: black;"><!--定义日志文件的路径--></span> <span style="color: black;"><<span style="color: black;">property</span> <span style="color: black;">name</span>=<span style="color: black;">"LOG_PATH"</span> <span style="color: black;">value</span>=<span style="color: black;">"${log.home}"</span>/></span> <span style="color: black;"><!--定义<span style="color: black;">掌控</span>台输出--></span> <span style="color: black;"><<span style="color: black;">appender</span> <span style="color: black;">name</span>=<span style="color: black;">"console"</span> <span style="color: black;">class</span>=<span style="color: black;">"ch.qos.logback.core.ConsoleAppender"</span>></span> <span style="color: black;"><<span style="color: black;">encoder</span>></span> <span style="color: black;"><<span style="color: black;">pattern</span>></span>%-5relative [%thread] %-5level %logger{35} - %msg%n<span style="color: black;"></<span style="color: black;">pattern</span>></span> <span style="color: black;"></<span style="color: black;">encoder</span>></span> <span style="color: black;"></<span style="color: black;">appender</span>></span> <span style="color: black;"><!--定义 INFO 及以上级别信息输出到<span style="color: black;">掌控</span>台--></span> <span style="color: black;"><<span style="color: black;">root</span> <span style="color: black;">level</span>=<span style="color: black;">"INFO"</span>></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"console"</span>/></span> <span style="color: black;"></<span style="color: black;">root</span>></span> <span style="color: black;"><!--定义所有组件的日志级别,如所有 DEBUG--></span> <span style="color: black;"><<span style="color: black;">logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.example"</span> <span style="color: black;">level</span>=<span style="color: black;">"DEBUG"</span>/></span> <span style="color: black;"><!-- date 格式定义 --></span> <span style="color: black;"><<span style="color: black;">property</span> <span style="color: black;">name</span>=<span style="color: black;">"LOG_DATEFORMAT"</span> <span style="color: black;">value</span>=<span style="color: black;">"yyyy-MM-dd"</span>/></span> <span style="color: black;"><!-- 定义日志归档文件名<span style="color: black;">叫作</span>格式,<span style="color: black;">每日</span>生成一个日志文件 --></span> <span style="color: black;"><<span style="color: black;">property</span> <span style="color: black;">name</span>=<span style="color: black;">"ARCHIVE_PATTERN"</span> <span style="color: black;">value</span>=<span style="color: black;">"${LOG_PATH}/%d{${LOG_DATEFORMAT}}/app-%d{${LOG_DATEFORMAT}}-%i.log.gz"</span>/></span> <span style="color: black;"><!--定义文件输出,会<span style="color: black;">按照</span>定义的阈值进行切割,支持自动归档压缩过期日志--></span> <span style="color: black;"><<span style="color: black;">appender</span> <span style="color: black;">name</span>=<span style="color: black;">"file"</span> <span style="color: black;">class</span>=<span style="color: black;">"ch.qos.logback.core.rolling.RollingFileAppender"</span>></span> <span style="color: black;"><<span style="color: black;">file</span>></span>${LOG_PATH}/app.log<span style="color: black;"></<span style="color: black;">file</span>></span> <span style="color: black;"><<span style="color: black;">rollingPolicy</span> <span style="color: black;">class</span>=<span style="color: black;">"ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"</span>></span> <span style="color: black;"><!--定义日志文件切割的阈值,本例是 50MB--></span> <span style="color: black;"><<span style="color: black;">maxFileSize</span>></span>50MB<span style="color: black;"></<span style="color: black;">maxFileSize</span>></span> <span style="color: black;"><!--定义日志文件<span style="color: black;">保存</span>时间,本例是<span style="color: black;">每日</span>生成一个日志文件--></span> <span style="color: black;"><<span style="color: black;">fileNamePattern</span>></span>${ARCHIVE_PATTERN}<span style="color: black;"></<span style="color: black;">fileNamePattern</span>></span> <span style="color: black;"><<span style="color: black;">maxHistory</span>></span>30<span style="color: black;"></<span style="color: black;">maxHistory</span>></span> <span style="color: black;"><!-- zip 压缩生成的归档文件 --></span> <span style="color: black;"><<span style="color: black;">timeBasedFileNamingAndTriggeringPolicy</span> <span style="color: black;">class</span>=<span style="color: black;">"ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"</span>></span> <span style="color: black;"><<span style="color: black;">maxFileSize</span>></span>50MB<span style="color: black;"></<span style="color: black;">maxFileSize</span>></span> <span style="color: black;"></<span style="color: black;">timeBasedFileNamingAndTriggeringPolicy</span>></span> <span style="color: black;"><!-- 删除过期文件 --></span> <span style="color: black;"><<span style="color: black;">cleanHistoryOnStart</span>></span>true<span style="color: black;"></<span style="color: black;">cleanHistoryOnStart</span>></span> <span style="color: black;"></<span style="color: black;">rollingPolicy</span>></span> <span style="color: black;"><<span style="color: black;">encoder</span>></span> <span style="color: black;"><<span style="color: black;">pattern</span>></span>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} - %msg%n<span style="color: black;"></<span style="color: black;">pattern</span>></span> <span style="color: black;"></<span style="color: black;">encoder</span>></span> <span style="color: black;"></<span style="color: black;">appender</span>></span> <span style="color: black;"><!--定义 ERROR 级别以上信息输出到文件--></span> <span style="color: black;"><<span style="color: black;">logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.example.demo"</span> <span style="color: black;">level</span>=<span style="color: black;">"ERROR"</span> <span style="color: black;">additivity</span>=<span style="color: black;">"false"</span>></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"file"</span>/></span> <span style="color: black;"></<span style="color: black;">logger</span>></span> <span style="color: black;"><!--异步输出日志信息--></span> <span style="color: black;"><<span style="color: black;">appender</span> <span style="color: black;">name</span>=<span style="color: black;">"asyncFile"</span> <span style="color: black;">class</span>=<span style="color: black;">"ch.qos.logback.classic.AsyncAppender"</span>></span> <span style="color: black;"><<span style="color: black;">discardingThreshold</span>></span>0<span style="color: black;"></<span style="color: black;">discardingThreshold</span>></span> <span style="color: black;"><<span style="color: black;">queueSize</span>></span>256<span style="color: black;"></<span style="color: black;">queueSize</span>></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"file"</span>/></span> <span style="color: black;"></<span style="color: black;">appender</span>></span> <span style="color: black;"><!--定义INFO及以上级别信息异步输出到文件--></span> <span style="color: black;"><<span style="color: black;">logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.example"</span> <span style="color: black;">level</span>=<span style="color: black;">"INFO"</span> <span style="color: black;">additivity</span>=<span style="color: black;">"false"</span>></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"asyncFile"</span>/></span> <span style="color: black;"></<span style="color: black;">logger</span>></span><span style="color: black;"></<span style="color: black;">configuration</span>></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">其中,<span style="color: black;">重点</span><span style="color: black;">包含</span>以下配置:</p><span style="color: black;">springProperty</span>定义了 log 文件的存储路径,<span style="color: black;">能够</span>通过 Spring 的属性文件配置方式进行设置,<span style="color: black;">倘若</span><span style="color: black;">无</span>配置则默认存储在 logs 目录下。<span style="color: black;">appender</span> 定义了日志输出的<span style="color: black;">目的</span>,<span style="color: black;">这儿</span><span style="color: black;">包含</span>了<span style="color: black;">掌控</span>台输出和文件输出两种,<span style="color: black;">详细</span><span style="color: black;">能够</span><span style="color: black;">按照</span><span style="color: black;">需要</span>进行配置。<span style="color: black;">root</span>定义了默认的日志级别和输出<span style="color: black;">目的</span>,默认<span style="color: black;">状况</span>下,INFO 级别以上的日志信息会输出到<span style="color: black;">掌控</span>台,<span style="color: black;">能够</span><span style="color: black;">按照</span><span style="color: black;">实质</span>需求进行修改。<span style="color: black;">logger</span> 定义了<span style="color: black;">区别</span>组件的日志级别和输出<span style="color: black;">目的</span>,例如,<span style="color: black;">这儿</span>定义了 com.example 这个组件的日志级别为 DEBUG,而 com.example.demo 这个组件的日志级别为 ERROR,并将其输出到文件中。<span style="color: black;">rollingPolicy</span>定义了日志文件的切割规则和归档策略,此处定义了日志文件<span style="color: black;">每一个</span> 50MB 进行切割,<span style="color: black;">每日</span>生成一个日志文件,并且压缩和删除过期文件,最多<span style="color: black;">保存</span> 30 天的日志文件。<span style="color: black;">encoder</span> 定义了日志信息的输出格式,<span style="color: black;">详细</span>的格式<span style="color: black;">能够</span><span style="color: black;">自动</span>定义。<span style="color: black;">asyncAppender</span> 定义了异步输出日志的方式,<span style="color: black;">针对</span>高并发时,<span style="color: black;">能够</span><span style="color: black;">运用</span>异步输出来<span style="color: black;">加强</span>系统的性能。<span style="color: black;">discardingThreshold</span> 定义了异步输出队列的阈值,当队列中的数据量超过此值时,会丢弃最早放入的数据,此处设置为 0 <span style="color: black;">暗示</span>队列不会丢弃任何数据。<span style="color: black;">queueSize</span> 定义了异步输出队列的<span style="color: black;">体积</span>,当队列满时,会等待队列中的数据被消费后再将数据放入队列中,此处设置为 256。3. 演示<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">咱们</span>新建一个普通工程(非spring工程),引用Logback后,把<span style="color: black;">以上</span>配置文件复制进logback.xml,<span style="color: black;">而后</span>将工程结构设置成如下模式</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">其中两个类的代码如下:</p><span style="color: black;">public</span> <span style="color: black;"><span style="color: black;">class</span> <span style="color: black;">Main</span> </span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{</p> <span style="color: black;">private</span> <span style="color: black;">static</span> <span style="color: black;">final</span> Logger log = LoggerFactory.getLogger(Main<span style="color: black;">.<span style="color: black;">class</span>)</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p> <span style="color: black;"><span style="color: black;">public</span> <span style="color: black;">static</span> <span style="color: black;">void</span> <span style="color: black;">main</span><span style="color: black;">(String[] args)</span> </span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{</p> log.trace(<span style="color: black;">"This is a Main trace message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p> log.debug(<span style="color: black;">"This is a Main debug message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p> log.info(<span style="color: black;">"This is a Main info message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p> log.warn(<span style="color: black;">"This is a Main warn message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p> log.error(<span style="color: black;">"This is a Main error message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> Slave.main(args);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p><span style="color: black;">public</span> <span style="color: black;"><span style="color: black;">class</span> <span style="color: black;">Slave</span> </span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{</p> <span style="color: black;">private</span> <span style="color: black;">static</span> <span style="color: black;">final</span>Logger log = LoggerFactory.getLogger(Slave<span style="color: black;">.<span style="color: black;">class</span>)</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">;</p> <span style="color: black;"><span style="color: black;">public</span> <span style="color: black;">static</span> <span style="color: black;">void</span> <span style="color: black;">main</span><span style="color: black;">(String[] args)</span> </span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">{</p> log.trace(<span style="color: black;">"This is a Slave trace message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p> log.debug(<span style="color: black;">"This is a Slave debug message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p> log.info(<span style="color: black;">"This is a Slave info message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p> log.warn(<span style="color: black;">"This is a Slave warn message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p> log.error(<span style="color: black;">"This is a Slave error message."</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">);</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"> }</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">}</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">我们想实现<span style="color: black;">这般</span>的效果,<span style="color: black;">首要</span>日志要<span style="color: black;">同期</span> 输出到<span style="color: black;">掌控</span>台 及 日志文件,且<span style="color: black;">区别</span>层级的代码,输出的日志层级<span style="color: black;">亦</span><span style="color: black;">区别</span>。<span style="color: black;">那样</span><span style="color: black;">咱们</span><span style="color: black;">能够</span>对<span style="color: black;">以上</span>的xml做出<span style="color: black;">有些</span><span style="color: black;">调节</span>:</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">由于</span>是非Spring项目,<span style="color: black;">因此</span> springProperty <span style="color: black;">这般</span>的标签就不要用了,<span style="color: black;">咱们</span>直接写死一个日志文件<span style="color: black;">位置</span><span style="color: black;">就可</span>。</p><span style="color: black;"><!--定义日志文件的路径--></span><span style="color: black;"><<span style="color: black;">property</span> <span style="color: black;">name</span>=<span style="color: black;">"LOG_PATH"</span> <span style="color: black;">value</span>=<span style="color: black;">"D://logs/log"</span>/></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">去掉原有的<span style="color: black;">哪些</span>root、logger标签,<span style="color: black;">咱们</span>自己新建两个logger,用于两个<span style="color: black;">区别</span>的层级。<span style="color: black;">咱们</span>想里层输出 debug 级别,外层输出info 级别,<span style="color: black;">咱们</span><span style="color: black;">能够</span>这么设置。并且<span style="color: black;">同期</span>输出到<span style="color: black;">掌控</span>台及日志文件</p><span style="color: black;"><<span style="color: black;">logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.zhanfu"</span> <span style="color: black;">level</span>=<span style="color: black;">"INFO"</span>></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"file"</span> /></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"console"</span>/></span><span style="color: black;"></<span style="color: black;">logger</span>></span><span style="color: black;"><<span style="color: black;">logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.zhanfu.child"</span> <span style="color: black;">level</span>=<span style="color: black;">"DEBUG"</span> <span style="color: black;">additivity</span>=<span style="color: black;">"false"</span>></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"file"</span> /></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"console"</span>/></span><span style="color: black;"></<span style="color: black;">logger</span>></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">当<span style="color: black;">咱们</span>运行Main.main的时候,就<span style="color: black;">能够</span>得到以下日志,slave 能输出debug级别,Main 只能输出 info及以上级别</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">4. 细节点<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">其实<span style="color: black;">咱们</span>上面的演示,有两个细节点,需要<span style="color: black;">重视</span>一下。一个<span style="color: black;">便是</span><span style="color: black;">咱们</span>的</p> <span style="color: black;"><<span style="color: black;">logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.zhanfu.child"</span> <span style="color: black;">level</span>=<span style="color: black;">"DEBUG"</span> <span style="color: black;">additivity</span>=<span style="color: black;">"false"</span>></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">运用</span>了一个 additivity="false" 的属性,这其实是<span style="color: black;">由于</span> logger 这个标签在锁定某个目录时,可能会<span style="color: black;">出现</span>层级关系。<span style="color: black;">例如</span><span style="color: black;">咱们</span>的两个 logger, 一个针对的目录是 com.zhanfu 另一个是 com.zhanfu.child ,后者就会被前者<span style="color: black;">包括</span>。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">当<span style="color: black;">咱们</span>的 com.zhanfu.child.Slave 打印日志时,当然会<span style="color: black;">运用</span>后者(更精确)的设置,但前者的设置还<span style="color: black;">运用</span>吗?就依赖于 additivity=“false”,此处<span style="color: black;">倘若</span><span style="color: black;">咱们</span>把 additivity="false" (该属性默认值为true)去掉,再来打印日志</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">就会<span style="color: black;">发掘</span>,Slave 的日志打了两遍,<span style="color: black;">况且</span>连 debug 级别的都打了两遍,<span style="color: black;">咱们</span><span style="color: black;">能够</span>把这种<span style="color: black;">规律</span>理解为继承,子类执行一遍,父类还能在执行一遍,但 leve 属性还是会采用子类而非父类的。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">另一点<span style="color: black;">便是</span><span style="color: black;">咱们</span>把 root 标签删除了,root 其实是一个顶级的 logger , 其他的logger都<span style="color: black;">能够</span>视为它的子类,<span style="color: black;">倘若</span><span style="color: black;">哪些</span>logger存在没涵盖的<span style="color: black;">地区</span>,或其<span style="color: black;">无</span>指定 additivity="false" ,那最后root的设置就会被<span style="color: black;">运用</span>。<span style="color: black;">例如</span><span style="color: black;">咱们</span>将设置改为如下:</p><span style="color: black;"><<span style="color: black;">logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.zhanfu"</span> <span style="color: black;">level</span>=<span style="color: black;">"INFO"</span>></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"file"</span> /></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"console"</span>/></span><span style="color: black;"></<span style="color: black;">logger</span>></span><span style="color: black;"><<span style="color: black;">logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.zhanfu.child"</span> <span style="color: black;">level</span>=<span style="color: black;">"DEBUG"</span>></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"file"</span> /></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"console"</span>/></span><span style="color: black;"></<span style="color: black;">logger</span>></span><span style="color: black;"><<span style="color: black;">root</span> <span style="color: black;">level</span>=<span style="color: black;">"WARN"</span>></span> <span style="color: black;"><<span style="color: black;">appender-ref</span> <span style="color: black;">ref</span>=<span style="color: black;">"console"</span>/></span><span style="color: black;"></<span style="color: black;">root</span>></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">结果<span style="color: black;">掌控</span>台的输出日志,Main会重复两次,Slave 会重复三次,如下</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">然则</span><span style="color: black;">由于</span><span style="color: black;">咱们</span>的 root 只配置了<span style="color: black;">掌控</span>台输出,<span style="color: black;">因此</span>日志文件里还是不会变的</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"><span style="color: black;">2. Log4j 2</span>1. 引用<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">针对</span>spring-boot项目,除了引用 Log4j 2 <span style="color: black;">咱们</span>还需要先剔除 Logback 的引用,<span style="color: black;">针对</span>普通项目,<span style="color: black;">咱们</span>只需直接引用<span style="color: black;">就可</span>。但<span style="color: black;">重视</span><span style="color: black;">咱们</span>的原则,<span style="color: black;">经过</span> SLF4J 来<span style="color: black;">运用</span> Log4j2,<span style="color: black;">因此</span>引用下面这个包</p><span style="color: black;"><<span style="color: black;">dependency</span>></span> <span style="color: black;"><<span style="color: black;">groupId</span>></span>org.apache.logging.log4j<span style="color: black;"></<span style="color: black;">groupId</span>></span> <span style="color: black;"><<span style="color: black;">artifactId</span>></span>log4j-slf4j-impl<span style="color: black;"></<span style="color: black;">artifactId</span>></span> <span style="color: black;"><<span style="color: black;">version</span>></span>2.13.3<span style="color: black;"></<span style="color: black;">version</span>></span><span style="color: black;"></<span style="color: black;">dependency</span>></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">其内<span style="color: black;">包括</span> Log4j2 的实现,和 SLF4J 的 API,如下:</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">2. 配置<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Log4j2 的配置<span style="color: black;">规律</span>和 logback 是类似的,<span style="color: black;">仅有</span>些细节<span style="color: black;">区别</span>,<span style="color: black;">例如</span>Logger 的首字母大写等等,最后<span style="color: black;">咱们</span>写下<span style="color: black;">这般</span>一个 log4j2.xml</p><span style="color: black;"><?xml version="1.0" encoding="UTF-8"?></span><span style="color: black;"><<span style="color: black;">Configuration</span> <span style="color: black;">status</span>=<span style="color: black;">"INFO"</span> <span style="color: black;">monitorInterval</span>=<span style="color: black;">"30"</span>></span> <span style="color: black;"><<span style="color: black;">Properties</span>></span> <span style="color: black;"><<span style="color: black;">Property</span> <span style="color: black;">name</span>=<span style="color: black;">"logPath"</span>></span>logs<span style="color: black;"></<span style="color: black;">Property</span>></span> <span style="color: black;"></<span style="color: black;">Properties</span>></span> <span style="color: black;"><<span style="color: black;">Appenders</span>></span> <span style="color: black;"><<span style="color: black;">Console</span> <span style="color: black;">name</span>=<span style="color: black;">"Console"</span> <span style="color: black;">target</span>=<span style="color: black;">"SYSTEM_OUT"</span>></span> <span style="color: black;"><<span style="color: black;">PatternLayout</span> <span style="color: black;">pattern</span>=<span style="color: black;">"%d{ISO8601} [%t] %-5level %logger{36} - %msg%n"</span> /></span> <span style="color: black;"></<span style="color: black;">Console</span>></span> <span style="color: black;"><<span style="color: black;">RollingFile</span> <span style="color: black;">name</span>=<span style="color: black;">"File"</span> <span style="color: black;">fileName</span>=<span style="color: black;">"${logPath}/example.log"</span> <span style="color: black;">filePattern</span>=<span style="color: black;">"${logPath}/example-%d{yyyy-MM-dd}-%i.log"</span>></span> <span style="color: black;"><<span style="color: black;">PatternLayout</span> <span style="color: black;">pattern</span>=<span style="color: black;">"%d{ISO8601} [%t] %-5level %logger{36} - %msg%n"</span>/></span> <span style="color: black;"><<span style="color: black;">Policies</span>></span> <span style="color: black;"><<span style="color: black;">SizeBasedTriggeringPolicy</span> <span style="color: black;">size</span>=<span style="color: black;">"10 MB"</span>/></span> <span style="color: black;"></<span style="color: black;">Policies</span>></span> <span style="color: black;"><<span style="color: black;">DefaultRolloverStrategy</span> <span style="color: black;">max</span>=<span style="color: black;">"4"</span>/></span> <span style="color: black;"></<span style="color: black;">RollingFile</span>></span> <span style="color: black;"></<span style="color: black;">Appenders</span>></span> <span style="color: black;"><<span style="color: black;">Loggers</span>></span> <span style="color: black;"><<span style="color: black;">Logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.zhanfu.child"</span> <span style="color: black;">level</span>=<span style="color: black;">"DEBUG"</span>></span> <span style="color: black;"><<span style="color: black;">AppenderRef</span> <span style="color: black;">ref</span>=<span style="color: black;">"File"</span>/></span> <span style="color: black;"><<span style="color: black;">AppenderRef</span> <span style="color: black;">ref</span>=<span style="color: black;">"Console"</span>/></span> <span style="color: black;"></<span style="color: black;">Logger</span>></span> <span style="color: black;"><<span style="color: black;">Logger</span> <span style="color: black;">name</span>=<span style="color: black;">"com.zhanfu"</span> <span style="color: black;">level</span>=<span style="color: black;">"INFO"</span>></span> <span style="color: black;"><<span style="color: black;">AppenderRef</span> <span style="color: black;">ref</span>=<span style="color: black;">"File"</span>/></span> <span style="color: black;"><<span style="color: black;">AppenderRef</span> <span style="color: black;">ref</span>=<span style="color: black;">"Console"</span>/></span> <span style="color: black;"></<span style="color: black;">Logger</span>></span> <span style="color: black;"><<span style="color: black;">Root</span> <span style="color: black;">level</span>=<span style="color: black;">"WARN"</span>></span> <span style="color: black;"><<span style="color: black;">AppenderRef</span> <span style="color: black;">ref</span>=<span style="color: black;">"Console"</span> /></span> <span style="color: black;"></<span style="color: black;">Root</span>></span> <span style="color: black;"></<span style="color: black;">Loggers</span>></span><span style="color: black;"></<span style="color: black;">Configuration</span>></span>Properties<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">部分定义了一个 logPath 属性,方便在其他<span style="color: black;">地区</span>引用。</p>Appenders<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">定义了两个 Appender:Console 和 RollingFile,分别将日志输出到<span style="color: black;">掌控</span>台和文件中。RollingFile <span style="color: black;">运用</span>了 RollingFileAppender,并设置了日志滚动策略和默认的备份文件数量。</p>Loggers<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">定义了三个 Logger:com.zhanfu.child 的日志级别为 DEBUG,com.zhanfu 的日志级别为INFO,Root Logger 的日志级别为 WARN。并指定了两个 Appender:Console 和 File。</p>3. 演示<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">因为</span><span style="color: black;">咱们</span>的配置<span style="color: black;">规律</span>没变,<span style="color: black;">因此</span>日志的结果还是<span style="color: black;">同样</span>的:</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"><span style="color: black;">3. 对比</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Log4j2和Logback都是Java应用程序中最流行的日志框架之一。它们均具备高度的可配置性和<span style="color: black;">运用</span>灵活性,并<span style="color: black;">供给</span>了一系列有用的功能,例如异步日志记录和日志过滤等。下面从配置遍历性、功能性、性能等方面进行比较和总结。</p>配置遍历性<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Logback的配置文件格式相对简单,易于阅读和修改。它支持符号来引用变量、属性和环境变量等。<span style="color: black;">另外</span>,它还支持<span style="color: black;">要求</span>日志记录(<span style="color: black;">按照</span>日志级别、日志记录器名<span style="color: black;">叫作</span>或时间等),以及滚动文件的<span style="color: black;">体积</span>或日期等。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Log4j2的配置文件格式较<span style="color: black;">繁杂</span>,但它在配置文件中<span style="color: black;">供给</span>了<span style="color: black;">海量</span>的选项来<span style="color: black;">掌控</span>日志记录。它支持在配置文件中直接声明上下文参数、过滤器、输出器和Appender等,这使得它的配置更加灵活。<span style="color: black;">另外</span>,Log4j2还支持异步日志记录、日志事件序列化和性能优化等。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">总体<span style="color: black;">来讲</span>,两者都很好地支持了配置遍历性,但Log4j2<span style="color: black;">供给</span>了<span style="color: black;">更加多</span>的选项和更高的灵活性。</p>功能性<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Logback<span style="color: black;">供给</span>了一系列基本的日志记录功能,例如异步Appender、滚动文件和GZIP压缩等。它还支持与SLF4J<span style="color: black;">一块</span><span style="color: black;">运用</span>,<span style="color: black;">能够</span>很容易地与其他日志框架集成。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Log4j2<span style="color: black;">供给</span>了<span style="color: black;">更加多</span>的高级功能,例如异步日志记录、性能优化和日志事件序列化等。它还支持Lambda表达式,<span style="color: black;">能够</span>使日志记录器更加简洁和易读。<span style="color: black;">另外</span>,Log4j2还支持Flume和Kafka等大数据处理框架,<span style="color: black;">能够</span>方便地将日志记录发送到这些框架中。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">总体<span style="color: black;">来讲</span>,Log4j2<span style="color: black;">供给</span>了<span style="color: black;">更加多</span>的高级功能,并且<span style="color: black;">能够</span>更好地与大数据处理框架集成。</p>性能<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Logback的性能很好,<span style="color: black;">能够</span>处理高吞吐量的日志记录。它采用了异步记录器,利用了多线程来<span style="color: black;">加强</span>性能。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Log4j2在性能方面更加强大。它<span style="color: black;">运用</span>了异步记录器和多线程,还引入了RingBuffer数据结构和Disruptor库来加速日志事件的传递和处理。这使得它比Logback<span style="color: black;">拥有</span>更高的吞吐量和更低的延迟。</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">综上所述,Log4j2在配置灵活性、功能性和性能方面都比Logback更为强大。但<span style="color: black;">倘若</span>需要轻量级的日志框架<span style="color: black;">或</span>只需要基本的日志记录功能,Logback<span style="color: black;">亦</span>是一个不错的<span style="color: black;">选取</span></span></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">但<span style="color: black;">倘若</span><span style="color: black;">咱们</span><span style="color: black;">同期</span>引用了这两者,会报错吗?还是会<span style="color: black;">运用</span>其中的某一个?</p> <span style="color: black;"><<span style="color: black;">dependency</span>></span> <span style="color: black;"><<span style="color: black;">groupId</span>></span>ch.qos.logback<span style="color: black;"></<span style="color: black;">groupId</span>></span> <span style="color: black;"><<span style="color: black;">artifactId</span>></span>logback-classic<span style="color: black;"></<span style="color: black;">artifactId</span>></span> <span style="color: black;"><<span style="color: black;">version</span>></span>1.2.12<span style="color: black;"></<span style="color: black;">version</span>></span><span style="color: black;"></<span style="color: black;">dependency</span>></span><span style="color: black;"><<span style="color: black;">dependency</span>></span> <span style="color: black;"><<span style="color: black;">groupId</span>></span>org.apache.logging.log4j<span style="color: black;"></<span style="color: black;">groupId</span>></span> <span style="color: black;"><<span style="color: black;">artifactId</span>></span>log4j-slf4j-impl<span style="color: black;"></<span style="color: black;">artifactId</span>></span> <span style="color: black;"><<span style="color: black;">version</span>></span>2.13.3<span style="color: black;"></<span style="color: black;">version</span>></span><span style="color: black;"></<span style="color: black;">dependency</span>></span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">能够</span>看到,SLF4J <span style="color: black;">发掘</span>了系统中<span style="color: black;">同期</span>存在两个插件框架,并<span style="color: black;">最后</span><span style="color: black;">选取</span>了<span style="color: black;">运用</span> Logback</p><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;">
<h3 style="color: black; text-align: left; margin-bottom: 10px;"><span style="color: black;">总结</span></h3>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">学习完本文,你应当对<span style="color: black;">此刻</span>这几个常用框架的有所<span style="color: black;">认识</span>,并能<span style="color: black;">基本</span>应用了。此次<span style="color: black;">咱们</span><span style="color: black;">无</span>讲源码,<span style="color: black;">亦</span><span style="color: black;">无</span>深入的讲其配置及进阶<span style="color: black;">运用</span>,这些<span style="color: black;">咱们</span>会在后面慢慢学习。但<span style="color: black;">此刻</span>我<span style="color: black;">期盼</span>你能<span style="color: black;">晓得</span>的是。<span style="color: black;">必定</span>要写好日志,<span style="color: black;">必定</span>要写好日志,<span style="color: black;">必定</span>要写好日志。重要的事情说三遍!这是区别新人和老鸟的一个重要依据,<span style="color: black;">亦</span>是让自己排查问题更<span style="color: black;">容易</span>的不二法门!</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">另一</span>,<span style="color: black;">此刻</span><span style="color: black;">非常多</span>中间件都自己引用了日志插件,<span style="color: black;">咱们</span><span style="color: black;">做为</span>一个整体工程在<span style="color: black;">运用</span>中间件时,要<span style="color: black;">即时</span><span style="color: black;">发掘</span>并<span style="color: black;">处理</span>插件冲突,避免<span style="color: black;">咱们</span>自己的日志配置失效,这<span style="color: black;">亦</span>是一个程序员该<span style="color: black;">重视</span>的点。</p><span style="color: black;"><span style="color: black;">源自</span>:blog.csdn.net/u011709538/</span><span style="color: black;">article/details/132363370</span>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">13 秒<span style="color: black;">插进</span> 30 万条数据,这才是批量<span style="color: black;">插进</span>正确的姿势!</a></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">和 XShell 说再见,这款 SSH 工具足够惊艳,还支持网页版!</a></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">我进入银行科技部半年,<span style="color: black;">已然</span>丧失跳槽的能力了!</a></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">程序员:有<span style="color: black;">那些</span>话一听就<span style="color: black;">晓得</span>对方很水 (段子)</a></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">23 </a>届校招技术岗薪资汇总</p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">面试官问我 ,try catch 应该在 for 循环里面还是外面?</a></p>
<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><a style="color: black;">再见了 shiro</a></p><span style="color: black;"><span style="color: black;">近期</span>面试BAT,整理一份面试资料</span><span style="color: black;">《<strong style="color: blue;">Java面试BAT通关手册</strong>》</span><span style="color: black;">,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。</span><span style="color: black;">获取方式:点“</span><span style="color: black;">在看</span><span style="color: black;">”,关注公众号并回复 </span><span style="color: black;">666</span><span style="color: black;">领取,<span style="color: black;">更加多</span>内容<span style="color: black;">持续</span>奉上。</span><span style="color: black;"><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"></span><strong style="color: blue;">明天见(。・ω・。</strong>
论坛外链网http://www.fok120.com/
页:
[1]