在tomcat 源代码中,有这样一个实用类: org.apache.catalina.util.StringManager,基本上每个tomcat组件(如:connector, container, realm, loader, logger等)都会用到它。这是一个管理异常消息的helper class。
像tomcat这样的Servlet容器,异常消息无论是对系统管理员或者程序员都非常重要。管理员可以通过异常消息,快速定位错误。而对于程序异常,tomcat将异常消息封装到ServletException,来告知程序员Servlet中的错误。
Tomcat如何管理这些异常消息呢?第一个要排除的是硬编码在代码中。这是十分不规范的做法,每一次编辑消息都要重新编译代码,非常麻烦。 Tomcat 将这些消息存入properties文件中,方便编辑。而且利用java的ResourceBundle类,可以方便的实现国际化,要知道tomcat是一个使用非常广泛的Servlet容器。然而,tomcat的核心包就有几百个类,如果将这些类要用到的异常消息存入一个properties文件,无疑会带来维护上的噩梦。
Tomcat的做法是一个包共用一个properties文件,如果大家机器上安装有tomcat,可以打开%TOMCAT_HOME%/server/lib的catalina.jar(tomcat最核心的包,catalina是tomcat的代号)看看,会发现里面基本上每一个包都含有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),以包名作为key,StringManager实例作为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);
}
}
分享到:
相关推荐
这种设计模式在iOS开发中非常常见,可以提高代码的复用性和灵活性。 在实际应用中,例如地图定位服务,用户可能输入中文地点名进行搜索,ChineseStringManager可以将这些中文字符串转换为拼音,然后与地图服务提供...
字符串管理器 核心:可运行类 ru.ifmo.ctddev.elite.core.CoreStarter <数据库的文件名> 数据库文件必须存在(至少为空)。 添加一名作者 编辑器:ru.ifmo.ctddev.elite.editor.StringEditor ...
(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)...
* $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 $ * * =...
3. **StringManager类**: - 用于管理和处理字符串对象,可能包括字符串的拼接、分割、替换等操作。 - 在语义标注过程中,字符串管理是非常关键的一环,例如处理复杂的命名实体识别、同义词替换等。 #### 使用...
1.DataValidator.cs 数据验证类,提供如...21.StringManager 字符串管理类 22.UploadFile 提供上传文件时所使用的方法 23.UploadFileManager 文件上传管理类 24.ValidateCode 可以生成验证码图像的类,图像格式为gif
为了使QtTreePropertyBrowser能够显示和编辑实际对象的属性,我们需要将这些属性与对象关联起来。这通常通过使用QtVariantPropertyManager和QtObjectPropertyManager来实现。 5. **事件处理** ...
重点讲解了StringManager类的作用,以及如何启动应用和配置连接器。 ### 第4章:Tomcat的默认连接器 这一章重点讲解了Tomcat的默认连接器实现——HttpConnector类。分析了HTTP/1.1协议的新特性,如持久化连接、...
总的来说,C#字符祖玛游戏的开发涵盖了C#语言的基础知识和高级特性,包括字符串操作、循环与条件判断、事件处理以及面向对象编程思想。通过实践这样的项目,开发者不仅可以巩固C#语法,还能提升算法设计和问题解决的...
#### 一、简介与概览 Tomcat作为一款开源的Servlet容器,被广泛应用于Java Web开发之中。它不仅能够运行Java Servlet,还支持JSP技术,是学习Java Web开发的理想平台之一。本文将深入探讨Tomcat的工作原理,包括其...
class StringManager { public: char* safe_strdup(const char *s) { if (s == NULL) { return NULL; } size_t len = strlen(s) + 1; char *copy = (char*)malloc(len); if (copy != NULL) { memcpy(copy, s...
#### 简介与概览 Tomcat作为一款开源的Servlet容器,被广泛应用于Java Web应用的开发与部署环境中。它不仅支持Servlet API,还支持JSP规范,使得开发者能够轻松地构建动态网页。本文旨在深入分析Tomcat的工作原理...
- **StringManager类**:用于国际化和本地化的字符串管理工具。 - **Application1**:实现一个简单的连接器示例,包括SocketInputStream、HttpRequest对象的创建及解析过程。 - **HttpResponse对象**:解析请求并...
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 小结 ...
Java与C语言的主要区别在于数据类型的表示范围不同,Java支持更大的数值范围。 - **常用数据类型**:主要包括`int`(整型)、`double`(双精度浮点型)、`boolean`(布尔型)、`byte`(字节型)等。值得注意的是`...
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...