亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Tomcat源碼分析(六)--日志記錄器和國際化

系統 1861 0
本系列轉載自?http://blog.csdn.net/haitao111313/article/category/1179996? ?

日志記錄器挺簡單的,沒有很多東西,最主要的就是一個Logger接口:

? ? ? ??

  1. public ? interface ?Logger?{??
  2. ???? public ? static ? final ? int ?FATAL?=?Integer.MIN_VALUE;??
  3. ???? public ? static ? final ? int ?ERROR?=? 1 ;??
  4. ???? public ? static ? final ? int ?WARNING?=? 2 ;??
  5. ???? public ? static ? final ? int ?INFORMATION?=? 3 ;??
  6. ???? public ? static ? final ? int ?DEBUG?=? 4 ;??
  7. ???? public ?Container?getContainer();??
  8. ???? public ? void ?setContainer(Container?container);??
  9. ???? public ?String?getInfo();??
  10. ???? public ? int ?getVerbosity();??
  11. ???? public ? void ?setVerbosity( int ?verbosity);??
  12. ???? public ? void ?addPropertyChangeListener(PropertyChangeListener?listener);??
  13. ???? public ? void ?log(String?message);??
  14. ???? public ? void ?log(Exception?exception,?String?msg);??
  15. ???? public ? void ?log(String?message,?Throwable?throwable);??
  16. ???? public ? void ?log(String?message,? int ?verbosity);??
  17. ???? public ? void ?log(String?message,?Throwable?throwable,? int ?verbosity);??
  18. ???? public ? void ?removePropertyChangeListener(PropertyChangeListener?listener);??
  19. }??
只要實現Logger就能有一個自己的日志記錄器,其中setContainer是把日志記錄器跟具體的容器關聯,setVerbosity是設置日志的級別,log是具體的日志記錄函數。FATAL,ERROR,WARNING,INFORMATION,DEBUG代表日志記錄的五個級別,看單詞就能明白意思。這里主要講解一下FileLogger類,這是Tomcat的其中一個日志記錄器,它把日志記錄在一個文件中,FileLogger的啟動方法和關閉僅僅是出發一個生命周期事件,并不做其他的事情:

  1. public ? void ?start()? throws ?LifecycleException?{??
  2. ??
  3. ?????? //?Validate?and?update?our?current?component?state ??
  4. ?????? if ?(started)??
  5. ?????????? throw ? new ?LifecycleException??
  6. ??????????????(sm.getString( "fileLogger.alreadyStarted" ));??
  7. ??????lifecycle.fireLifecycleEvent(START_EVENT,? null ); //觸發生命周期事件 ??
  8. ??????started?=? true ;??
  9. ??
  10. ??}??
這里有一行代碼sm.getString("fileLogger.alreadyStarted"),牽涉到國際化的問題,等下再說這個問題。現在先看日志記錄器,FileLogger的open方法打開一個文件用來記錄日志:

  1. private ? void ?open()?{??
  2. ??
  3. ??????? //?Create?the?directory?if?necessary ??
  4. ???????File?dir?=? new ?File(directory); //directory等于logs,即在文件夾logs下新建日志文件 ??
  5. ??????? if ?(!dir.isAbsolute())??
  6. ???????????dir?=? new ?File(System.getProperty( "catalina.base" ),?directory);??
  7. ???????dir.mkdirs();??
  8. ??
  9. ??????? //?Open?the?current?log?file ??
  10. ??????? try ?{??
  11. ???????????String?pathname?=?dir.getAbsolutePath()?+?File.separator?+??
  12. ???????????????prefix?+?date?+?suffix;??
  13. ???????????writer?=? new ?PrintWriter( new ?FileWriter(pathname,? true ),? true );??
  14. ???????}? catch ?(IOException?e)?{??
  15. ???????????writer?=? null ;??
  16. ???????}??
  17. ??
  18. ???}??
這里得到一個PrintWriter的輸出流writer,在log方法記錄日志的時候會用到,下面看log方法:
  1. public ? void ?log(String?msg)?{??
  2. ??
  3. ?????? //?Construct?the?timestamp?we?will?use,?if?requested ??
  4. ??????Timestamp?ts?=? new ?Timestamp(System.currentTimeMillis());??
  5. ??????String?tsString?=?ts.toString().substring( 0 ,? 19 );??
  6. ??????String?tsDate?=?tsString.substring( 0 ,? 10 );??
  7. ??
  8. ?????? //?If?the?date?has?changed,?switch?log?files ??
  9. ?????? if ?(!date.equals(tsDate))?{?? //如果日期改變,則新建一個日志文件。 ??
  10. ?????????? synchronized ?( this )?{??
  11. ?????????????? if ?(!date.equals(tsDate))?{??
  12. ??????????????????close();??
  13. ??????????????????date?=?tsDate;??
  14. ??????????????????open();??
  15. ??????????????}??
  16. ??????????}??
  17. ??????}??
  18. ??
  19. ?????? //?Log?this?message,?timestamped?if?necessary ??
  20. ?????? if ?(writer?!=? null )?{??
  21. ?????????? if ?(timestamp)?{??
  22. ??????????????writer.println(tsString?+? "?" ?+?msg); //寫入時間和日志信息進日志文件中。 ??
  23. ??????????}? else ?{??
  24. ??????????????writer.println(msg);??
  25. ??????????}??
  26. ??????}??
  27. ??
  28. ??}??


writer.println把時間和日志信息寫進日志文件中。當然,這個日志記錄器一般是給Tomcat自己用的,我們也可以實現Logger接口,然后重寫它的open方法(打開我們自己的日志文件)和log方法(用來在我們自己的日志文件中記錄日志信息)。

現在再來看剛才提到的代碼sm.getString("fileLogger.alreadyStarted")。在理解這句代碼前先看一個jdk的類ResourceBundle,這個類提供了國際化的方便。這個類的作用就是讀取.properties文件,但是會根據文件名來獲取當前系統的語言信息,然后讀取對應文件的屬性值。當然首先要有各國不同的屬性文件,才能國際化,Tomcat的每個包下都有幾個不同的屬性文件,org.apache.catalina.logger包下有如下三個屬性文件:

  1. LocalStrings_es.properties??
  2. LocalStrings_ja.properties??
  3. LocalStrings.properties??
分別表示三種語言的屬性文件。LocalStrings.properties屬性文件是默認的屬性文件。看LocalStrings.properties屬性中的內容:

  1. fileLogger.alreadyStarted=File?Logger?has?already?been?started??
  2. fileLogger.notStarted=File?Logger?has?not?yet?been?started??
  3. tomcatLogger.alreadyStarted=Tomcat?Logger?has?already?been?started??
  4. tomcatLogger.notStarted=Tomcat?Logger?has?not?yet?been?started??

ResourceBundle類通過getBundle方法獲取,參數是屬性文件的包名家名字前綴,上面就是包名加LocalStrings。通過getString(String key)方法獲取屬性文件中的參數:
現在來看代碼sm.getString("fileLogger.alreadyStarted"),sm是StringManager的實例,在FileLogger中已經初始化:

  1. private ?StringManager?sm?=StringManager.getManager(Constants.Package);??

Constants.Package得到包的名字,getManager方法代碼如下:

  1. public ? synchronized ? static ?StringManager?getManager(String?packageName)?{??
  2. ???????StringManager?mgr?=?(StringManager)managers.get(packageName);??
  3. ??????? if ?(mgr?==? null )?{??
  4. ???????????mgr?=? new ?StringManager(packageName); //新建一個StringManager ??
  5. ???????????managers.put(packageName,?mgr);??
  6. ???????}??
  7. ??????? return ?mgr;??
  8. ???}??

代碼很好理解,如果已經有StringManager實例了就直接從managers(這是一個Hashtable)中拿,沒有就新建一個。看StringManager的構造方法:
  1. private ?StringManager(String?packageName)?{??
  2. ???????String?bundleName?=?packageName?+? ".LocalStrings" ;??
  3. ???????bundle?=?ResourceBundle.getBundle(bundleName);??
  4. ???}??
看到我們熟悉的ResourceBundle類了,根據上面的講解,ResourceBundle.getBundle(bundleName)能拿到默認的屬性文件,也就是上面的LocalStrings.properties文件。再回到sm.getString("fileLogger.alreadyStarted"),看sm的getString方法:

  1. public ?String?getString(String?key)?{??
  2. ??????? if ?(key?==? null )?{??
  3. ???????????String?msg?=? "key?is?null" ;??
  4. ??
  5. ??????????? throw ? new ?NullPointerException(msg);??
  6. ???????}??
  7. ??
  8. ???????String?str?=? null ;??
  9. ??
  10. ??????? try ?{??
  11. ???????????str?=?bundle.getString(key);??
  12. ???????}? catch ?(MissingResourceException?mre)?{??
  13. ???????????str?=? "Cannot?find?message?associated?with?key?'" ?+?key?+? "'" ;??
  14. ???????}??
  15. ??
  16. ??????? return ?str;??
  17. ???}??

重點是budle.getString(key),這句代碼能拿到LocalStrings.properties文件的key屬性(這里是fileLogger.alreadyStarted)的值,即File Logger has already been started。這樣我們便能定義多個屬性文件,一個表示英文,一個表示漢語,一個屬性文件表示一個語言,就能實現應用的國際化了。

Tomcat源碼分析(六)--日志記錄器和國際化


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产亚洲精品欧美一区 | 国产伊人影院 | 福利午夜最新 | 97在线观看视频免费 | 国产一区二区三区在线观看免费 | 午夜精品久久久久久久99热浪潮 | 婷婷五月色综合香五月 | 99久久精品费精品国产一区二区 | baoyu777永久免费视频 | 天天做天天爱夜夜爽女人爽宅 | 亚洲日本va中文字幕在线不卡 | 亚洲国产高清精品线久久 | 深夜在线网址 | 自拍在线视频 | 国产成人丝袜网站在线观看 | 欧美精品在欧美一区二区 | 在线观看国产久青草 | 亚洲视频高清 | 在线成人tv天堂中文字幕 | 最新国产精品亚洲 | 久久国产香蕉 | 四虎影视国产在线观看精品 | 九九影院理论片私人影院 | 免费观看黄色小视频 | 在线亚洲一区二区 | 欧美一级毛片在线观看 | 免费看一级欧美毛片 | www色婷婷| 免费观看久久 | 久久久久久久久久免费视频 | 欧美性xxx免费看片 欧美性白人顶级hd 欧美性插视频 | 国产伦精品一区二区三区免费迷 | 免费看真人a一级毛片 | 人人综合 | 青青青在线视频人视频在线 | 久久怡红院国产精品 | 九九51精品国产免费看 | 一级特黄aa大片欧美小说 | 精品国产免费观看一区 | 久久经典免费视频 | 性感美女香蕉视频 |