日志組件slf4j介紹及配置詳解

本文轉自云棲社區(qū)-點擊可以查看原文

1 基本介紹

每一個Java程序員都知道日志對于任何一個Java應用程序出刷,尤其是服務端程序是至關重要的兵志,而很多程序員也已經(jīng)熟悉各種不同的日志庫如java.util.logging椎镣、Apache log4j艺晴、logback冗美。但如果你還不知道SLF4J(Simple logging facade for Java)的話魔种,那么是時候去在你項目中學習使用SLF4J了。

SLF4J不同于其他日志類庫粉洼,與其它日志類庫有很大的不同节预。SLF4J(Simple logging Facade for Java)不是一個真正的日志實現(xiàn),而是一個抽象層( abstraction layer)属韧,它允許你在后臺使用任意一個日志類庫安拟。如果是在編寫供內(nèi)外部都可以使用的API或者通用類庫,那么你真不會希望使用你類庫的客戶端必須使用你選擇的日志類庫宵喂。

如果一個項目已經(jīng)使用了log4j糠赦,而你加載了一個類庫,比方說 Apache Active MQ——它依賴于于另外一個日志類庫logback樊破,那么你就需要把它也加載進去愉棱。但如果Apache Active MQ使用了SLF4J唆铐,你可以繼續(xù)使用你的日志類庫而無需忍受加載和維護一個新的日志框架的痛苦哲戚。

總的來說,SLF4J使你的代碼獨立于任意一個特定的日志API艾岂,這是一個對于開發(fā)API的開發(fā)者很好的思想顺少。雖然抽象日志類庫的思想已經(jīng)不是新鮮的事物而且Apache commons logging也已經(jīng)在使用這種思想了,但現(xiàn)在SLF4J正迅速成為Java世界的日志標準。讓我們再看看幾個使用SLF4J而不是log4j脆炎、logback或者java.util.logging的理由梅猿。

2 SLF4J對比Log4J,logback和java.util.Logging的優(yōu)勢

正如我之前說的秒裕,在你的代碼中使用SLF4J寫日志語句的主要出發(fā)點是使得你的程序獨立于任意特定的日志類庫袱蚓,依賴于特定類可能需要不同與你已有的配置,并且導致更多維護的麻煩几蜻。

但除此之外喇潘,還要一個SLF4J API的特性使得我堅持使用SLF4J而拋棄我長期間鐘愛的Lof4j的理由,是被稱為占位符(place holder)梭稚,在代碼中表示為“{}”的特性颖低。占位符是一個非常類似于在String的format()方法中的%s,因為它會在運行時被某個提供的實際字符串所替換弧烤。這不僅降低了你代碼中字符串連接次數(shù)忱屑,而且還節(jié)省了新建的String對象。即使你可能沒需要那些對象暇昂,但這個依舊成立莺戒,取決于你的生產(chǎn)環(huán)境的日志級別,例如在DEBUG或者INFO級別的字符串連接急波。因為String對象是不可修改的并且它們建立在一個String池中脏毯,它們消耗堆內(nèi)存( heap memory)而且大多數(shù)時間他們是不被需要的,例如當你的應用程序在生產(chǎn)環(huán)境以ERROR級別運行時候幔崖,一個String使用在DEBUG語句就是不被需要的食店。通過使用SLF4J,你可以在運行時延遲字符串的建立,這意味著只有需要的String對象才被建立赏寇。而如果你已經(jīng)使用log4j吉嫩,那么你已經(jīng)對于在if條件中使用debug語句這種變通方案十分熟悉了,但SLF4J的占位符就比這個好用得多嗅定。

這是你在Log4j中使用的方案自娩,但肯定這一點都不有趣并且降低了代碼可讀性因為增加了不必要的繁瑣重復代碼(boiler-plate code):

if (logger.isDebugEnabled()) {
    logger.debug("Processing trade with id: " + id + " symbol: " + symbol);
}

另一方面,如果你使用SLF4J的話渠退,你可以得到在極簡潔的格式的結果忙迁,就像以下展示的一樣:

logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);

在SLF4J,我們不需要字符串連接而且不會導致暫時不需要的字符串消耗碎乃。取而代之的姊扔,我們在一個以占位符和以參數(shù)傳遞實際值的模板格式下寫日志信息。你可能會在想萬一我有很個參數(shù)怎么辦梅誓?嗯寻拂,那么你可以選擇使用變量參數(shù)版本的日志方法或者用以Object數(shù)組傳遞。這是一個相當?shù)姆奖愫透咝Х椒ǖ拇蛉罩痉椒ū脸S涀。谏a(chǎn)最終日志信息的字符串之前嗅回,這個方法會檢查一個特定的日志級別是不是打開了,這不僅降低了內(nèi)存消耗而且預先降低了CPU去處理字符串連接命令的時間摧茴。這里是使用SLF4J日志方法的代碼绵载,來自于slf4j-log4j12-1.6.1.jar中的Log4j的適配器類Log4jLoggerAdapter

public void debug(String format, Object arg1, Object arg2) {
    if (logger.isDebugEnabled()) {
        FormattingTuple ft = MessageFormatter.format(format, arg1, arg2);
        logger.log(FQCN, Level.DEBUG, ft.getMessage(), ft.getThrowable());
    }
}

同時苛白,我們也有必要知道打日志是對應用程序的性能有著很大影響的尘分,在生產(chǎn)環(huán)節(jié)建議只是在必要的時候打日志。

3 使用配置

3.1 maven依賴

<dependency>
  <groupId>org.slf4j</groupId>
  <artifactId>slf4j-api</artifactId>
  <version>1.7.21</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.1.2</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>1.1.2</version>
</dependency>

3.2 日志系統(tǒng)配置

假設現(xiàn)有如下程序:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Main {
    private static final Logger logger = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        int status = 0;
        if (status == 0) {
            logger.info("status:{}", status);
        } else {
            logger.info("status:{}", status);
        }
        logger.info("end!");
    }
}

可以使用以下兩種方式對日志系統(tǒng)的輸出格式丸氛、記錄級別培愁、輸出方式等進行配置:

  • 使用properties文件方式
  • 使用xml文件方式
3.2.1 properties文件方式

log4j.properties:

log4j.rootLogger=info, ServerDailyRollingFile, stdout
log4j.appender.ServerDailyRollingFile=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ServerDailyRollingFile.DatePattern='.'yyyy-MM-dd
log4j.appender.ServerDailyRollingFile.File=logs/notify-subscription.log
log4j.appender.ServerDailyRollingFile.layout=org.apache.log4j.PatternLayout
log4j.appender.ServerDailyRollingFile.layout.ConversionPattern=%d - %m%n
log4j.appender.ServerDailyRollingFile.Append=true
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH\:mm\:ss} %p [%c] %m%n

輸出結果為:

2016-05-12 16:08:21 INFO [club.chuxing.learn.Main] status:0
2016-05-12 16:08:21 INFO [club.chuxing.learn.Main] end!

3.2.2 xml文件方式
  1. 首先pom中添加如下依賴:
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-core</artifactId>
  <version>1.1.7</version>
</dependency>
<dependency>
  <groupId>ch.qos.logback</groupId>
  <artifactId>logback-classic</artifactId>
  <version>1.1.7</version>
</dependency>
  1. 設置日志配置的xml文件 logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <!-- 應用名稱 -->
    <property name="APP_NAME" value="logtest" />
    <!--日志文件的保存路徑,首先查找系統(tǒng)屬性-Dlog.dir,如果存在就使用其;否則缓窜,在當前目錄下創(chuàng)建名為logs目錄做日志存放的目錄 -->
    <property name="LOG_HOME" value="${log.dir:-logs}/${APP_NAME}" />
    <!-- 日志輸出格式 -->
    <property name="ENCODER_PATTERN"
              value="%d{yyyy-MM-dd  HH:mm:ss.SSS} [%thread] %-5level %logger{80} - %msg%n" />
    <contextName>${APP_NAME}</contextName>

    <!-- 控制臺日志:輸出全部日志到控制臺 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <Pattern>${ENCODER_PATTERN}</Pattern>
        </encoder>
    </appender>

    <!-- 文件日志:輸出全部日志到文件 -->
    <appender name="FILE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/output.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${ENCODER_PATTERN}</pattern>
        </encoder>
    </appender>

    <!-- 錯誤日志:用于將錯誤日志輸出到獨立文件 -->
    <appender name="ERROR_FILE"
              class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${ENCODER_PATTERN}</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>WARN</level>
        </filter>
    </appender>

    <!-- 獨立輸出的同步日志 -->
    <appender name="SYNC_FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_HOME}/sync.%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>7</maxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${ENCODER_PATTERN}</pattern>
        </encoder>
    </appender>

    <logger name="log.sync" level="DEBUG" addtivity="true">
        <appender-ref ref="SYNC_FILE" />
    </logger>

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

輸出結果為:

2016-05-12 17:08:32.105 [main] INFO club.chuxing.learn.Main - status:0
2016-05-12 17:08:32.114 [main] INFO club.chuxing.learn.Main - end!

3.3 日志系統(tǒng)配置說明

3.3.1 輸出級別的種類
  • ERROR 為嚴重錯誤 主要是程序的錯誤
  • WARN 為一般警告定续,比如session丟失
  • INFO 為一般要顯示的信息,比如登錄登出
  • DEBUG 為程序的調(diào)試信息
3.3.2 配置日志信息輸出目的地

log4j.appender.appenderName=??

org.apache.log4j.ConsoleAppender(控制臺)
org.apache.log4j.FileAppender(文件)
org.apache.log4j.DailyRollingFileAppender(每天產(chǎn)生一個日志文件)
org.apache.log4j.RollingFileAppender(文件大小到達指定尺寸的時候產(chǎn)生一個新的文件)
org.apache.log4j.WriterAppender(將日志信息以流格式發(fā)送到任意指定的地方)
3.3.3 配置日志信息的格式

log4j.appender.appenderName.layout = ??

org.apache.log4j.HTMLLayout(以HTML表格形式布局)
org.apache.log4j.PatternLayout(可以靈活地指定布局模式)
org.apache.log4j.SimpleLayout(包含日志信息的級別和信息字符串)
org.apache.log4j.TTCCLayout(包含日志產(chǎn)生的時間禾锤、線程私股、類別等等信息)
3.3.4 ConsoleAppender選項
  • Threshold=DEBUG:指定日志消息的輸出最低層次。
  • ImmediateFlush=true:默認值是true,意謂著所有的消息都會被立即輸出恩掷。
  • Target=System.err:默認情況下是System.out,指定輸出控制臺
3.3.5 FileAppender 選項
  • Threshold=DEBUG:指定日志消息的輸出最低層次倡鲸。
  • ImmediateFlush=true:默認值是true,意謂著所有的消息都會被立即輸出。
  • File=mylog.txt:指定消息輸出到mylog.txt文件黄娘。
  • Append=false:默認值是true,即將消息增加到指定文件中峭状,false指將消息覆蓋指定的文件內(nèi)容。
3.3.6 RollingFileAppender 選項
  • Threshold=DEBUG:指定日志消息的輸出最低層次逼争。
  • ImmediateFlush=true:默認值是true,意謂著所有的消息都會被立即輸出优床。
  • File=mylog.txt:指定消息輸出到mylog.txt文件。
  • Append=false:默認值是true,即將消息增加到指定文件中誓焦,false指將消息覆蓋指定的文件內(nèi)容胆敞。
  • MaxFileSize=100KB: 后綴可以是KB, MB 或者是 GB. 在日志文件到達該大小時,將會自動滾動杂伟,即將原來的內(nèi)容移到mylog.log.1文件移层。
  • MaxBackupIndex=2:指定可以產(chǎn)生的滾動文件的最大數(shù)。
3.3.7 日志信息格式中幾個符號所代表的含義
  • -X號: X信息輸出時左對齊赫粥;
  • %p: 輸出日志信息優(yōu)先級观话,即DEBUG,INFO傅是,WARN匪燕,ERROR蕾羊,F(xiàn)ATAL,
  • %d: 輸出日志時間點的日期或時間喧笔,默認格式為ISO8601帽驯,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS}书闸,輸出類似:2002年10月18日 22:10:28尼变,921
  • %r: 輸出自應用啟動到輸出該log信息耗費的毫秒數(shù)
  • %c: 輸出日志信息所屬的類目,通常就是所在類的全名
  • %t: 輸出產(chǎn)生該日志事件的線程名
  • %l: 輸出日志事件的發(fā)生位置浆劲,相當于%C.%M(%F:%L)的組合,包括類目名嫌术、發(fā)生的線程,以及在代碼中的行數(shù)牌借。舉例:Testlog4.main (TestLog4.java:10)
  • %x: 輸出和當前線程相關聯(lián)的NDC(嵌套診斷環(huán)境),尤其用到像java servlets這樣的多客戶多線程的應用中度气。
  • %%: 輸出一個”%”字符
  • %F: 輸出日志消息產(chǎn)生時所在的文件名稱
  • %L: 輸出代碼中的行號
  • %m: 輸出代碼中指定的消息,產(chǎn)生的日志具體信息
  • %n: 輸出一個回車換行符,Windows平臺為”\r\n”膨报,Unix平臺為”\n”輸出日志信息換行
一個示例配置文件
log4j.debug=true   
log4j.rootLogger=DEBUG,D,E

log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File = logs/logs.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = DEBUG
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
log4j.appender.D.File = logs/error.log
log4j.appender.D.Append = true
log4j.appender.D.Threshold = ERROR
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

過濾器

過濾器磷籍,執(zhí)行一個過濾器會有返回個枚舉值,即DENY现柠,NEUTRAL院领,ACCEPT其中之一。返回DENY够吩,日志將立即被拋棄不再經(jīng)過其他過濾器比然;返回NEUTRAL,有序列表里的下個過濾器過接著處理日志周循;返回ACCEPT强法,日志會被立即處理,不再經(jīng)過剩余過濾器湾笛。
過濾器被添加到<Appender>中拟烫,為<Appender> 添加一個或多個過濾器后,可以用任意條件對日志進行過濾迄本。<Appender> 有多個過濾器時硕淑,按照配置順序執(zhí)行。

下面是幾個常用的過濾器:

  • LevelFilter: 級別過濾器嘉赎,根據(jù)日志級別進行過濾置媳。如果日志級別等于配置級別,過濾器會根據(jù)onMath 和 onMismatch接收或拒絕日志公条。有以下子節(jié)點:
    • <level>:設置過濾級別
    • <onMatch>:用于配置符合過濾條件的操作
    • <onMismatch>:用于配置不符合過濾條件的操作
  • ThresholdFilter: 臨界值過濾器拇囊,過濾掉低于指定臨界值的日志。當日志級別等于或高于臨界值時靶橱,過濾器返回NEUTRAL寥袭;當日志級別低于臨界值時路捧,日志會被拒絕。
    例如:過濾掉所有低于INFO級別的日志传黄。
  • EvaluatorFilter: 求值過濾器杰扫,評估、鑒別日志是否符合指定條件膘掰。有子節(jié)點:
    <evaluator>: 鑒別器章姓,常用的鑒別器是JaninoEventEvaluato,也是默認的鑒別器识埋,它以任意的Java布爾值表達式作為求值條件凡伊,求值條件在配置文件解釋過成功被動態(tài)編譯,布爾值表達式返回true就表示符合過濾條件窒舟。evaluator有個子標簽<expression>系忙,用于配置求值條件。
    求值表達式作用于當前日志惠豺,logback向求值表達式暴露日志的各種字段:
Name Type Description
event LoggingEvent 與記錄請求相關聯(lián)的原始記錄事件银还,下面所有變量都來自event,例如耕腾,event.getMessage()返回下面”message”相同的字符串
message String 日志的原始消息见剩,例如,設有l(wèi)ogger mylogger扫俺,”name”的值是”AUB”苍苞,對于 mylogger.info(“Hello {}”,name); “Hello {}”就是原始消息。
formatedMessage String 日志被各式話的消息狼纬,例如羹呵,設有l(wèi)ogger mylogger,”name”的值是”AUB”疗琉,對于 mylogger.info(“Hello {}”,name); “Hello Aub”就是格式化后的消息冈欢。
logger String logger 名。
loggerContext LoggerContextVO 日志所屬的logger上下文盈简。
level int 級別對應的整數(shù)值凑耻,所以 level > INFO 是正確的表達式。
timeStamp long 創(chuàng)建日志的時間戳柠贤。
marker Marker 與日志請求相關聯(lián)的Marker對象香浩,注意“Marker”有可能為null,所以你要確保它不能是null臼勉。
mdc Map 包含創(chuàng)建日志期間的MDC所有值得map邻吭。訪問方法是:mdc.get(“myKey”) 。mdc.get()返回的是Object不是String宴霸,要想調(diào)用String的方法就要強轉囱晴,例如膏蚓,((String) mdc.get(“k”)).contains(“val”) .MDC可能為null,調(diào)用時注意畸写。
throwable java.lang.Throwable 如果沒有異常與日志關聯(lián)”throwable” 變量為 null. 不幸的是驮瞧, “throwable” 不能被序列化。在遠程系統(tǒng)上永遠為null艺糜,對于與位置無關的表達式請使用下面的變量throwableProxy
throwableProxy IThrowableProxy 與日志事件關聯(lián)的異常代理剧董。如果沒有異常與日志事件關聯(lián)幢尚,則變量”throwableProxy” 為 null. 當異常被關聯(lián)到日志事件時破停,”throwableProxy” 在遠程系統(tǒng)上不會為null

<onMatch>:用于配置符合過濾條件的操作
<onMismatch>:用于配置不符合過濾條件的操作
例如:過濾掉所有日志消息中不包含“billing”字符串的日志。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尉剩,一起剝皮案震驚了整個濱河市真慢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌理茎,老刑警劉巖黑界,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異皂林,居然都是意外死亡朗鸠,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門础倍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烛占,“玉大人,你說我怎么就攤上這事沟启∫浼遥” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵德迹,是天一觀的道長芽卿。 經(jīng)常有香客問我,道長胳搞,這世上最難降的妖魔是什么卸例? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮肌毅,結果婚禮上筷转,老公的妹妹穿的比我還像新娘。我一直安慰自己芽腾,他們只是感情好旦装,可當我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著摊滔,像睡著了一般阴绢。 火紅的嫁衣襯著肌膚如雪店乐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天呻袭,我揣著相機與錄音眨八,去河邊找鬼。 笑死左电,一個胖子當著我的面吹牛廉侧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播篓足,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼段誊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了栈拖?” 一聲冷哼從身側響起连舍,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎涩哟,沒想到半個月后索赏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡贴彼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年潜腻,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片器仗。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡融涣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出青灼,到底是詐尸還是另有隱情暴心,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布杂拨,位于F島的核電站专普,受9級特大地震影響,放射性物質發(fā)生泄漏弹沽。R本人自食惡果不足惜檀夹,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望策橘。 院中可真熱鬧炸渡,春花似錦、人聲如沸丽已。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至吼畏,卻和暖如春督赤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泻蚊。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工躲舌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人性雄。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓没卸,卻偏偏與公主長得像,于是被迫代替她去往敵國和親秒旋。 傳聞我的和親對象是個殘疾皇子约计,可洞房花燭夜當晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)滩褥,斷路器病蛉,智...
    卡卡羅2017閱讀 134,669評論 18 139
  • 歷史 log4j可以當之無愧地說是Java日志框架的元老炫加,1999年發(fā)布首個版本瑰煎,2012年發(fā)布最后一個版本,20...
    kelgon閱讀 10,162評論 3 53
  • 在應用程序中添加日志記錄總的來說基于三個目的:監(jiān)視代碼中變量的變化情況俗孝,周期性的記錄到文件中供其他應用進行統(tǒng)計分析...
    時待吾閱讀 5,052評論 1 13
  • 在應用程序中添加日志記錄總的來說基于三個目的:監(jiān)視代碼中變量的變化情況酒甸,周期性的記錄到文件中供其他應用進行統(tǒng)計分析...
    時待吾閱讀 4,988評論 0 6
  • 最近看到一篇文章,說的是服務不能彌補產(chǎn)品滿意度赋铝,也就是說你服務做的再好插勤,產(chǎn)品質量不行還是留不住顧客。假如買了一部手...
    胡義華閱讀 221評論 0 0