扯淡:空闲时间不多,扯淡时间久更少了。
主题:
先了解下两个所谓的知识点: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 } }
在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; } }
总结:记得以前连单例是神马都不知道,现如今可以按包给单例,我想还会有更多变化可以学习。没有做不到,只有想不到,哈哈。
让我们继续前行
----------------------------------------------------------------------
努力不一定成功,但不努力肯定不会成功。
共勉