`
lh870003574
  • 浏览: 23398 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

StringManager与单例模式

阅读更多

    tomcat 源代码中,有这样一个实用类: org.apache.catalina.util.StringManager,基本上每个tomcat组件(如:connector, container, realm, loader, logger等)都会用到它。这是一个管理异常消息的helper class

 

    tomcat这样的Servlet容器,异常消息无论是对系统管理员或者程序员都非常重要。管理员可以通过异常消息,快速定位错误。而对于程序异常,tomcat将异常消息封装到ServletException,来告知程序员Servlet中的错误。

 

    Tomcat如何管理这些异常消息呢?第一个要排除的是硬编码在代码中。这是十分不规范的做法,每一次编辑消息都要重新编译代码,非常麻烦。 Tomcat 将这些消息存入properties文件中,方便编辑。而且利用javaResourceBundle类,可以方便的实现国际化,要知道tomcat是一个使用非常广泛的Servlet容器。然而,tomcat的核心包就有几百个类,如果将这些类要用到的异常消息存入一个properties文件,无疑会带来维护上的噩梦。

 

    Tomcat的做法是一个包共用一个properties文件,如果大家机器上安装有tomcat,可以打开%TOMCAT_HOME%/server/libcatalina.jar(tomcat最核心的包,catalinatomcat的代号)看看,会发现里面基本上每一个包都含有LocalString.properties文件,如:org.apache.core,就是这些文件,存储了tomcat所要用到的异常消息。

 

    StringManager就是为了处理这些异常消息的helper class, 当包中的某个类需要用到异常消息时,可以先实例化StringManager,然后调用getString(String key)方法

 

sm.getString("httpConnector.alreadyInitialized")

上面的语句返回“HTTP connector has already been initialized

如果你有LocalStrings_CN.properties文件,则会返回相应的中文消息。

 

    然而,若每个类都实例化一个StringManager对象,而这些对象所包含的异常消息都是相同的,同样也会带来资源上的浪费。若每个包中的类,都共用一个StringManager对象,则会大大的提高效率。怎么做到这一点呢?读到这里,相信熟悉设计模式的读者应该都会想到了吧~  没错,就是单例模式。

   

单例

         单例模式是对象的创建模式,确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

 

/**
 * 单例模式
 * @author linhai
 */
public class Singleton {
	
	//声明一个静态的实例
	private static Singleton instance;
	
	//私有化构造函数
	private Singleton(){}
	
	//静态方法返回自身实例
	public static Singleton getInstance()
	{
		if(instance==null)
		{
			instance=new Singleton();
		}
		return instance;
	}

}

 

 

 

    上面的代码便是单例模式的经典示例。单例的要点有二:一是私有化构造函数,这样其它的类不能进行实行化,保证单例,第二是要提供静态的工厂方法,返回自身实例,让客户端调用:Singleton instance=Singleton.getInstance()

 

 

  

 

 

 

StringManager

         明白了单例模式,要实现一个包只有一个StringManager对象便简单了,可以采用一个Map(tomcat 采用的是HashTable),以包名作为keyStringManager实例作为value

 

package com.scnulh.catalina.util;

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

public class StringManager {
	
	/**
	 * ResourceBundle实例,代表存储tomcat异常消息的资源文件
	 */
	private ResourceBundle bundle;
	
	/**
	 * 保存StringManager对象的Map,以包名为key,value为StringManager对象
	 */
	private static Map<String, StringManager> stringManagers=
		new HashMap<String, StringManager>();
	
	/**
	 * 私有化的构造函数
	 * @param packageName  包名
	 */
	private StringManager(String packageName)
	{
		//包名加LocalStrings,这也是为什么我们看的资源文件是以LocalStrings命名的原因
		String baseName=packageName+".LocalStrings";
		//根据包名,获取资源文件
		bundle=ResourceBundle.getBundle(baseName);
	}
	
	/**
	 * 返回StringManager实例的静态方法,确保相同的包名返回相同的实例
	 * 同步方法	
	 * @param packageName  包名
	 * @return
	 */
	public synchronized static StringManager getStringManager(String packageName)
	{
		//先从map中查找
		StringManager stringManager=stringManagers.get(packageName);
		
		//如果对应包的StringManager未实例化,则实例化,并且放入Map中缓存
		if(stringManager==null)
		{
			stringManager=new StringManager(packageName);
			stringManagers.put(packageName, stringManager);
		}
		return stringManager;
	}
	
	
	//============以下为StringManager对象查找异常消息的方法===========
	public String getString(String key)
	{
		//对参数先进行验证
		if(key==null)
		{
			String msg="key is null";
			throw new NullPointerException(msg);
		}
		String result=null;
		try
		{
			result=bundle.getString(key);
		}
		catch(MissingResourceException e)
		{
			result="can not find message with the key "+key;
		}
		
		return result;
	}
	
	public String getString(String key,Object[] args)
	{
		String result=null;
		String initMessage=getString(key);
		
		try
		{
			Object[] notNullArgs=args;
			for(int i=0;i<args.length;i++)
			{
				if(args[i]==null)
				{
					if(notNullArgs==args)
						notNullArgs=(Object[])args.clone();
					args[i]="null";
				}
			}
			//MessageFormat的使用
			result=MessageFormat.format(initMessage, notNullArgs);
		}
		//这里异常的处理值得我们学习
		//估计大部分的程序员都会直接来一句iae.printStackTrace();吧
		catch(IllegalArgumentException iae)
		{
			StringBuilder sb=new StringBuilder();
			sb.append(initMessage);
			for (int i = 0; i < args.length; i++) {
                sb.append(" arg[" + i + "]=" + args[i]);
            }
			result=sb.toString();
			
		}
		return result;
	}
	//以下是方法的重载,方便客户端的调用
	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);
	}
	
	public static void main(String[] args)
	{
		StringManager stringManager=
			StringManager.getStringManager("ex03.pyrmont.connector.http");
		String string=stringManager.getString("httpConnector.alreadyInitialized");	
		
		System.out.println(string);
		
		string=stringManager.getString("httpConnector.anAddress", "192.165.23.26",12);
		System.out.println(string);

	}

}

 

 

1
5
分享到:
评论
3 楼 lh870003574 2012-08-30  
liuyes 写道
//以下是方法的重载,避免都调用getString(String key,Object[] args)  
//效率会更高

这个效率会高?(什么效率?)应该写方便使用吧,呵呵

看的挺认真的~~你说的对,以下那几个重载的方法都调用了getString(String key,Object[] args)  不是为了提高效率,而是为了调用的方便。
之所以写这两行注释,是因为我看错了,以为和java的可变形参有关,而可变形参对性能确实有点影响~  已经改过来了,谢谢提醒~
2 楼 liuyes 2012-08-30  
//以下是方法的重载,避免都调用getString(String key,Object[] args)  
//效率会更高

这个效率会高?(什么效率?)应该写方便使用吧,呵呵
1 楼 sconio 2012-08-30  
谢谢分享,值得学习一下

相关推荐

    StringManager

    字符串管理器 核心:可运行类 ru.ifmo.ctddev.elite.core.CoreStarter &lt;数据库的文件名&gt; 数据库文件必须存在(至少为空)。 添加一名作者 编辑器:ru.ifmo.ctddev.elite.editor.StringEditor ...

    ChineseStringManager

    输入中文字符串,在编辑状态结束后会自动将中文转为拼音和简拼,封装的Category还有其他的方法,用在地图定位中文搜索地理位置时用的上哦

    apache-tomcat-7.0.21-embed.zip

    (1) 确认“JDK+Tomcat”的运行环境已经搭建好。 (2) 从光盘中将shopping目录拷贝到电脑中,这里假定拷贝在“D:\shopping”,即把包含了网上购物系统所有文件的shopping目录放到D盘中。 (3) 在Tomcat安装目录的conf\...

    跟我学汉化(含gif动画)汉化新世纪官方作品

     (6)NSIS (7)StringManager (8)Passlo (9)AutoFontSet (10)Sisulizer  (11)灵便汉化编辑器 (12)VBLocalize (13)FreeRes (14)PE-scan (15)DictionaryHelper  (16)ExeinfoPE (17)点睛字符替换器 (18)ResHacker (19)...

    SocketInputStream.java

    * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/util/StringManager.java,v 1.2 2001/07/22 20:25:14 pier Exp $ * $Revision: 1.2 $ * $Date: 2001/07/22 20:25:14 $ * * =...

    C# 常用类代码(封装)

    1.DataValidator.cs 数据验证类,提供如...21.StringManager 字符串管理类 22.UploadFile 提供上传文件时所使用的方法 23.UploadFileManager 文件上传管理类 24.ValidateCode 可以生成验证码图像的类,图像格式为gif

    《深入剖析Tomcat(中文版+英文版)》.rar

    3.1 stringmanager类 3.2 应用程序 3.2.1 启动应用程序 3.2.2 httpconnector类 3.2.3 创建httprequest对象 3.2.4 创建httpresponse对象 3.2.5 静态资源处理器和servlet处理器 3.2.6 运行应用程序 3.3 小结 ...

    How Tomcat Works: A Guide to Developing Your Own Java Servlet Container

    3.2 StringManager类 11 3.3 Application 12 3.3.1 启动 13 3.3.2 connector 13 3.3.3 创建HttpRequest对象 13 3.3.3.1 SocketInputStream类 14 3.3.3.2 解析请求行(request line) 14 3.3.3.3 解析请求头(request...

    how-tomcat-works

    3.2 StringManager类 11 3.3 Application 12 3.3.1 启动 13 3.3.2 connector 13 3.3.3 创建HttpRequest对象 13 3.3.3.1 SocketInputStream类 14 3.3.3.2 解析请求行(request line) 14 3.3.3.3 解析请求头(request...

Global site tag (gtag.js) - Google Analytics