讓System.out.println回家種田

來源:互聯網
上載者:User

讓System.out.println回家種田,換句話說,就是該幹嘛幹嘛去。

您可能在想: System.out.println幾乎在每個Java程式裡都有那麼幾行,如何讓他老人家回家種田呢? 我們怎麼能少了這麼重要的革命同志呢?

doodoofish這裡要說的是"該幹嘛幹嘛去",不是System.out.println管的就別讓他管。想想,我們用System.out.println (文中稱SOP,不是Service Oriented Programming,是System.out.println) 主要在三種情況下:

一、輸出文本到stdout,作為輸出結果;

二、顯示調試資訊,用來Debug;

三、顯示資訊,讓管理員觀賞

第一種情況,沒得說,是SOP的老本行,不服不行。讓他就繼續幹吧。

第二、三種情況,就不該SOP管,讓他管也管不好。如果我調試用SOP來顯示資訊,一旦哪天我決定不要顯示這些煩人的東西了,怎麼辦? 好辦啊,一個檔案一個檔案找,一行一行找,把SOP給Comment起來不就完了,多方便啊。可是哪天我又要顯示這些調試資訊了,又怎麼辦? 第二天我又不要了,下個月我又要了... ... 我們程式員閑得慌嗎? 可有人就是認為我們很閑,你的老闆可能就是一個。我的朋友5bug是個天才,他說有辦法,就是每個SOP前加一個 if 來判斷是否顯示。天才啊!

我比較笨,比郭靖還笨。我就沒想到這個法子,一直沒想出來,直到上10個星期,看到一篇介紹Log4J的文章。一開始看不懂 (我比較笨) ,倒過來看一遍總算懂了。

說起來又是一個類庫,在http://logging.apache.org/site/binindex.cgi這裡下載。然後就把那個log4j1.2.8.jar從"dist/lib"目錄下copy到我的項目LogTest的"lib"目錄下 (真煩,copy檔案是很煩人的操作,需要一定的技術)。然後,我就寫了個簡單的class (複雜的我不會寫) 來調用log4j的東東。

import

org.apache.log4j.*;

public

class LogTest {

    static Logger logger = Logger.getLogger(LogTest.class.getName());

    public static void main(String[] args) {

        logger.debug("Debug ...");

        logger.info("Info ...");

        logger.warn("Warn ...");

        logger.error("Error ...");

    }

}

沒什麼新鮮,就是個Logger。那"static Logger logger = Logger.getLogger(LogTest.class.getName());" 就是建立一個屬於LogTest類的Logger對象,建立時要告知Logger你當前的Class是什麼,所以就有了"LogTest.class.getName()"這奇怪的東東。

logger.debug就是輸出debug的資訊

logger.info就是輸出提示資訊

logger.warn就是顯示警告資訊

logger.error就是顯示錯誤資訊

log是什麼? Log是個很深奧的古希臘名詞,不貶義,也不褒義。說簡單了,就是"日誌",就是你要寫什麼就寫什麼,要寫哪裡就是哪裡。不同與SOP,log4j可以讓你把要寫的東西分成4級 (其實有更多級,你可以自己定義,比如叫: 三級++),這些層級叫優先權 (Priority),這裡四個優先權就是debug, info, warn, 和error,優先權從低到高,log4j能讓你控制顯示哪些優先權的資訊。log4j也讓你要寫哪就哪,可以是螢幕,可以是一個檔案,甚至是一個Email,一個XML,一個Socket,等等。這些控制都在一個小檔案裡,叫log4j.properties (其實你可以用其它名字,這裡是預設名)。這個檔案在工程目錄下。以下是log4j.properties的內容:

#### Use one appender to log to console

log4j.rootCategory=DEBUG, stdout

#### Appender writes to console

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

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

log4j.appender.stdout.layout.ConversionPattern=%5p (%F:%L) - %m%n

就是說我要顯示所有優先權等於和高於Debug的資訊,所以上面那個Class會顯示Debug ...,Info ...,Warn ...,Error ...所有資訊。

"stdout"表示我定義了一個輸出端,叫stdout (隨便什麼名字都好)。

下面的三行說,這個stdout輸出端其實是標準輸出Console,也就是螢幕。輸出的格式是Pattern。轉換方式是%5p (%F:%L) - %m%n,即前五格用來顯示優先權,再顯示當前的檔案名稱,加當前的行數。最後是logger.debug()或logger.info()或logger.warn()或logger.error()裡的資訊。%n表示斷行符號空行。

運行程式,最後輸出的是:

DEBUG (LogTest.java:9) - Debug ...

INFO (LogTest.java:10) - Info ...

WARN (LogTest.java:11) - Warn ...

ERROR (LogTest.java:12) - Error ...

搞了半天,最後就輸出這麼個東西? 對啊。有人就說了,"還不如System.out.println呢"。不過你看看,你做了些什麼。

一、下載了log4j,copy類庫到工程的lib目錄

二、寫一個log4j.properties檔案 (4行)

三、在Class裡加了"static Logger logger = Logger.getLogger(LogTest.class.getName());"一句話

四、用logger.xxx來輸出資訊。

完了。你得到的若干好處是:

一、在log4j.properties檔案裡把"log4j.rootCategory=DEBUG, stdout"改寫成"log4j.rootCategory=OFF, stdout",這樣所有的log資訊都不會顯示了;

二、在log4j.properties檔案裡把"log4j.rootCategory=DEBUG, stdout"改寫成"log4j.rootCategory=INFO, stdout",這樣只顯示INFO, WARN, ERROR的log資訊,而DEBUG資訊不會被顯示;

三、在log4j.properties檔案裡把"log4j.rootCategory=DEBUG, stdout"改寫成"log4j.rootCategory=DEBUG, stdout, R",再加上下面三句話:

log4j.appender.R=org.apache.log4j.RollingFileAppender

log4j.appender.R.File=log.txt

log4j.appender.R.MaxFileSize=100KB

log4j.appender.R.MaxBackupIndex=1

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

log4j.appender.R.layout.ConversionPattern=%d{yyyy MMM dd HH:mm:ss} %-5p %c - %m%n

這樣,你的log資訊不光顯示在螢幕上,而且將被儲存在一個叫"log.txt"的檔案裡,檔案最大為100KB。如果檔案大小超過100KB,檔案會被備份成"log.txt.1",新的"log.txt"繼續記錄log資訊。

你可以改變log4j.properties,而不需重新編譯就可以控制log資訊是否顯示、log資訊的輸出端類型、輸出方式、輸出格式,等等。你上面的四步工作帶來這麼多好處,我還要System.out.println來顯示log資訊嗎? 不需要了。

 

以下是我LogTest項目的目錄結構:

build.xml檔案的內容:

<project

name="Log4j Test" default="build" basedir=".">

    <property name="app.home" value="${basedir}" />

    <property name="app.src" value="${app.home}/src" />

    <property name="app.bin" value="${app.home}/bin" />

    <property name="app.lib" value="${app.home}/lib" />

    <path id="classpath">

        <fileset dir="${app.lib}">

            <include name="**/*.jar" />

        </fileset>

        <path location="${app.home}"/>

        <path location="${app.bin}"/>

    </path>

    <target name="init">

        <mkdir dir="${app.bin}"/>

    </target>

    <target name="build" depends="init" description="compile the source " >

        <javac srcdir="${app.src}" destdir="${app.bin}">

            <classpath refid="classpath"/>

        </javac>

    </target>

    <target name="run" description="run">

        <java classname="LogTest" dir="${app.bin}" fork="true">

            <classpath refid="classpath"/>

        </java>

    </target>

    <target name="clean" description="clean up" >

        <delete dir="${app.bin}" />

    </target>

</project>

總共四個檔案,一個用來測試的LogTest類,一個build.xml ANT檔案,一個log4j.properties配製檔案,一個log4j-1.2.8.jar類庫。

log4j的功能有很多,doodoofish這裡就不詳細介紹了,以下是參考文獻:

  • Don't Use System.out.println! Use Log4j by Vipan Singla

  • Build Flexible Logs With log4j by Vikram Goyal

  • log4j by Ashley J.S Mills, University Of Birmingham

  • Add logging to your Java Applications by Kevin Brown

  • How does the Java logging API stack up against log4j? by Kevin Brown

  • OpenSymphony Logging Primer

  • log4j FAQ at jGuru

     

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.