最近在阅读《How Tomcat Works》这本书,书中提到了Tomcat中对各种异常进行处理的方式。像Tomcat这种应用,错误消息对于系统管理员和servlet程序员来说都是很有用的。Tomcat中处理错误消息的方法是将错误消息存储在一个properties文件中,便于读取和编辑,但是Tomcat中有几百个类。若是将所有类的错误消息都存储在一个大的properties属性文件中,并维护这个文件将是一个噩梦。为了避免这种情况,Tomcat将properties文件划分到不同的包中,例如org.apache.catalina.core包下的properties属性文件包含该包中的任何类可能抛出的所有异常的信息,每个properties文件都是用org.apache.tomcat.util.res. StringManager类的一个实例来处理的。当Tomcat运行时,会产生StringManager类的很多实例,每个实例都会读取某个包下指定的properties文件。
当包中的某个类需要在其包内的properties文件中查找错误消息时,它会先获取对应的StringManager实例。但是,同一个包下的许多类会使用同一个StringManager实例,若是为每个要查找错误消息的对象创建一个StringManager实例是很浪费资源的。因此,设计StringManager类以便StringManager类的实例被保内所有的对象共享,在Tomcat中使用单例模式来处理这个问题,所以StringManager类是个单例类。StringManager只有一个私有的构造函数,这样就不能在类的外部通过new来实例化它了。只能通过调用其公用静态方法getManager()来获取其实例,该方法需要一个指明了包名的参数。每个StringManager实例都会以这个包名作为其键存储在一个Hashtable中。
代码实现如下:
publicstaticfinalsynchronized StringManager getManager(
String packageName, Locale locale) {
Map<Locale,StringManager> map = managers.get(packageName);
if (map == null) {
map = new Hashtable<Locale, StringManager>();
managers.put(packageName, map);
}
StringManager mgr = map.get(locale);
if (mgr == null) {
mgr = new StringManager(packageName, locale);
map.put(locale, mgr);
}
return mgr;
}
使用方法如下:
根据包名称获取到对应的实例:
/**
* The string manager for this package.
*/
protectedstaticfinal StringManager sm =
StringManager.getManager(Constants.Package);
在程序中使用:
publicvoid addChild(Container child) {
thrownew IllegalStateException
(sm.getString("standardWrapper.notChild"));
}