zoukankan      html  css  js  c++  java
  • Tomcat StringManager阅读学习 我们到底能走多远系列(10)

    我们到底能走多远系列(10)

    扯淡:空闲时间不多,扯淡时间久更少了。

    主题:

     先了解下两个所谓的知识点:ResourceBundle 和 MessageFormat

    在项目里用的得心应手的properites文件,大多要用到这两个类吧。

    java.util.ResourceBundle
    java.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.Drvier
    database.url=jdbc:mysql://localhost:3306:test
    database.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;
        }
    }


    总结:记得以前连单例是神马都不知道,现如今可以按包给单例,我想还会有更多变化可以学习。没有做不到,只有想不到,哈哈。

    让我们继续前行

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

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

  • 相关阅读:
    WampServer Mysql配置
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 陶陶摘苹果2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 质因数2
    Java实现 蓝桥杯VIP 算法提高 前10名
  • 原文地址:https://www.cnblogs.com/killbug/p/2728551.html
Copyright © 2011-2022 走看看