Tomcat StringManager閱讀學習 -我們到底能走多遠系列(10)

來源:互聯網
上載者:User
我們到底能走多遠系列(10)

扯淡:空閑時間不多,扯淡時間久更少了。

主題:

 先瞭解下兩個所謂的知識點:ResourceBundle 和 MessageFormat

在項目裡用的得心應手的properites檔案,大多要用到這兩個類吧。

java.util.ResourceBundlejava.text.MessageFormat

1,ResourceBundle解析資源檔分兩步:1載入資源檔,2擷取資源檔中的資訊

// 載入資源檔ResourceBundle resource = ResourceBundle.getBundle("messages");// 擷取資源檔中的資訊String driverName = resource.getString("database.driver");

ResourceBundle支援多國語言:先把檔案名稱取成類似這樣myres_zh_CN.properties

然後:

Locale locale1 = new Locale("zh", "CN");ResourceBundle resb1 = ResourceBundle.getBundle("myres", locale1);
resb1.getString("aaa");

2,MessageFormat用來格式化一個訊息(字串嘛)

直接網上類似代碼:

String pig = "{0}{1}{2}{3}{4}{5}{6}{7}{8}{9}{10}{11}{12}{13}{14}{15}{16}";  Object[] array = new Object[]{"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q"};  String value = MessageFormat.format(pig, array);  System.out.println(value);  //最終結果是:ABCDEFGHIJKLMNOPQ

3,結合在一起就可以實現,將properites檔案解析出想要的訊息體,然後格式化後給上一層方法用。

 

myResources.properties:

database.driver=com.mysql.jdbc.Drvierdatabase.url=jdbc:mysql://localhost:3306:testdatabase.user={0}database.pass={0}

例:

public class ResourceBundleTest {    public static void main(String[] args) {        // 指明包路徑和檔案名稱即可        ResourceBundle resource = ResourceBundle.getBundle("code.stu.ResourceBundle.myResources");        String driverName = resource.getString("database.driver");        String url = resource.getString("database.url");        Object[] array1 = new Object[]{"root"};        Object[] array2 = new Object[]{"test"};        // 取得字串,直接格式化        String user = MessageFormat.format(resource.getString("database.user"), new Object[]{"root"});        String pass = MessageFormat.format(resource.getString("database.pass"), new Object[]{"test"});        System.out.println(driverName + url + user + pass);//結果:com.mysql.jdbc.Drvierjdbc:mysql://localhost:3306:testroottest    }}
StringManager

在tomcat裡,把錯誤記錄檔資訊的字串寫在properites檔案裡,如此一來,列印日誌的事情就可以通過上面的兩個類來解決了。

StringManager是管理列印日誌的類,Tomcat的設計是,對每一個包提供自己的properites檔案,也就是說,每一個包的日誌資訊只需要去各自包的properites檔案裡去找就可以了,然後Tomcat為每一個包提供一個StringManager執行個體,相當於一個包一個單例的效果(值得學習下)。各自的StringManager執行個體來管理各自包下的日誌列印。

源碼如下:

package org.apache.catalina.util;import java.text.MessageFormat;import java.util.Hashtable;import java.util.Locale;import java.util.MissingResourceException;import java.util.ResourceBundle;import java.net.URLClassLoader;public class StringManager {    // ResourceBundle用於讀取properties檔案    private ResourceBundle bundle;        private static org.apache.juli.logging.Log log=        org.apache.juli.logging.LogFactory.getLog( StringManager.class );        // 私人的構造方法能夠保證外界無法執行個體化自己,這也是單例實現的關鍵步驟    private StringManager(String packageName) {        // properties檔案所在的package+“.LocalStrings”        // 所有tomcat的日誌使用的properties檔案都依照這個形式來命名的        String bundleName = packageName + ".LocalStrings";        try {            // 根據bundleName取得解析資源檔的執行個體            bundle = ResourceBundle.getBundle(bundleName);            return;        } catch( MissingResourceException ex ) {// 好吧,異常就先不管了。            // Try from the current loader ( that's the case for trusted apps )            ClassLoader cl=Thread.currentThread().getContextClassLoader();            if( cl != null ) {                try {                    bundle=ResourceBundle.getBundle(bundleName, Locale.getDefault(), cl);                    return;                } catch(MissingResourceException ex2) {                }            }            if( cl==null )                cl=this.getClass().getClassLoader();            if (log.isDebugEnabled())                log.debug("Can't find resource " + bundleName +                    " " + cl);            if( cl instanceof URLClassLoader ) {                if (log.isDebugEnabled())                     log.debug( ((URLClassLoader)cl).getURLs());            }        }    }    /**     * Get a string from the underlying resource bundle.     *     * @param key The resource name     */    public String getString(String key) {        return MessageFormat.format(getStringInternal(key), (Object [])null);    }    protected String getStringInternal(String key) {        // key 還是要保證不是null        if (key == null) {            String msg = "key is null";            throw new NullPointerException(msg);        }        // 返回string        String str = null;        if( bundle==null )            return key;        try {            // 資源檔裡去查有沒有對應的內容            str = bundle.getString(key);        } catch (MissingResourceException mre) {            str = "Cannot find message associated with key '" + key + "'";        }        return str;    }    public String getString(String key, Object[] args) {        String iString = null;        String value = getStringInternal(key);        // this check for the runtime exception is some pre 1.1.6        // VM's don't do an automatic toString() on the passed in        // objects and barf out        try {            // ensure the arguments are not null so pre 1.2 VM's don't barf            Object nonNullArgs[] = args;            for (int i=0; i<args.length; i++) {                if (args[i] == null) {                    if (nonNullArgs==args) nonNullArgs=(Object[])args.clone();                    nonNullArgs[i] = "null";                }            }            // 格式化,就是把一些變化的參數插入到value這個string中去,格式化成一個新的最終的string            iString = MessageFormat.format(value, nonNullArgs);        } catch (IllegalArgumentException iae) {            StringBuffer buf = new StringBuffer();            buf.append(value);            for (int i = 0; i < args.length; i++) {                buf.append(" arg[" + i + "]=" + args[i]);            }            iString = buf.toString();        }        return iString;    }    // 下面四個getString方法,最終都需要調用getString(String key, Object[] args)    public String getString(String key, Object arg) {        Object[] args = new Object[] {arg};        return getString(key, args);    }    public String getString(String key, Object arg1, Object arg2) {        Object[] args = new Object[] {arg1, arg2};        return getString(key, args);    }    public String getString(String key, Object arg1, Object arg2,                            Object arg3) {        Object[] args = new Object[] {arg1, arg2, arg3};        return getString(key, args);    }    public String getString(String key, Object arg1, Object arg2,                            Object arg3, Object arg4) {        Object[] args = new Object[] {arg1, arg2, arg3, arg4};        return getString(key, args);    }        // Hashtable維護整個tomcat的StringManager    private static Hashtable managers = new Hashtable();    // 保證一個包一個StringManager,私人化建構函式+Hashtable維護實現(值得學習)    // 從而避免大量的StringManager執行個體化和銷毀的操作,畢竟寫日誌屬於比較頻繁的操作。    public synchronized static StringManager getManager(String packageName) {        // 用一個Hashtable來管理控制,保證每個包提供一個StringManager        StringManager mgr = (StringManager)managers.get(packageName);        // 屬於這個包的Manager有了嗎        if (mgr == null) {            mgr = new StringManager(packageName);            // 執行個體化好後,把它放進Hashtable裡去,下次就不用執行個體化了            managers.put(packageName, mgr);        }        return mgr;    }}

總結:記得以前連單例是神馬都不知道,現如今可以按包給單例,我想還會有更多變化可以學習。沒有做不到,只有想不到,哈哈。

 

讓我們繼續前行

----------------------------------------------------------------------

努力不一定成功,但不努力肯定不會成功。
共勉

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.