且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

《深入剖析Tomcat》一3.1 StringManager类

更新时间:2022-09-24 22:50:17

3.1 StringManager类

像Tomcat这样的大型应用程序必须小心仔细地处理错误消息。在Tomcat中,错误消息对系统管理员和servlet程序员来说都是很有用的。例如,系统管理员可以很容易地根据Tomcat的错误日志消息定位到发生异常的位置。而对于servlet程序员来说,在抛出的每个javax.servlet.servletException异常中,Tomcat都会发送一条特殊的错误消息,这样,程序员就可以知道servlet程序到底哪里出错了。
Tomcat处理错误消息的方法是将错误消息存储在一个properties文件中,便于读取和编辑。但是Tomcat中有几百个类。若是将所有类使用的错误消息都存储在一个大的properties属性文件中,并维护这个文件将会是一场噩梦。为了避免这种情况,Tomcat将properties文件划分到不同的包中。例如,org.apache.catalina.connector包下的properties属性文件包含该包中任何类可能抛出的所有的异常消息。每个properties文件都是用org.apache.catalina.util.StringManager类的一个实例来处理的。当Tomcat运行时,会产生StringManager类的很多实例,每个实例都会读取某个包下的指定properties文件。此外,由于Tomcat非常受欢迎,因此对错误消息进行国际化处理也是有必要的,当前共有三种语言得到支持。使用英文版错误消息的properties文件命名为LocalStrings.properties。其他两种语言是西班牙语和日语,错误消息文件分别名为LocalStrings_es.properties和LocalStrings_ja.properties。
当包中的某个类需要在其包内的properties文件中查找错误消息时,它会先获取对应的StringManager实例。但是,同一个包下的许多类会使用同一个StringManager实例,若是为每个要查找错误消息的对象创建一个StringManger实例是很浪费资源的。因此,设计StringManager类以便StringManager类的实例被包内所有的对象共享。若你对设计模式比较熟悉的话,你可能已经猜到了,StringManager是单例类。StringManager只有一个私有的构造函数,这样就不能在类的外部通过关键字new来实例化它了。只能通过调用其公共静态方法getManager()来获得其实例,该方法需要一个指明了包名的参数。每个StringManager实例都会以这个包名作为其键,存储在一个Hashtable中。
《深入剖析Tomcat》一3.1 StringManager类

注意 在附加的ZIP文件中有一篇名为“The Singleton Pattern”的文章,其中会对单例模式进行讲解。
例如,要想从ex03.pyrmont.connector.http包下的类中使用StringManager,需要将包名字符串作为参数传到StringManager类的getManager()方法中:

StringManager sm = 
              StringManager.getManager("ex03.pyrmont.connector.http");

在ex03.pyrmont.connector.http包下,可以找到三个properties文件,LocalStrings.properties、LocalStrings_es.properties和LocalStrings_ja.properties。StringManager实例会根据运行该应用程序的服务器的语言环境来选择使用哪个文件。若打开LocalStrings.properties文件,第1个非注释行的内容如下:

httpConnector.alreadyInitialized=HTTP connector has already been initialized

要想获取错误消息,可以使用StringManager类的getString()方法,该方法需要传入一个错误码。其中一个重载方法的签名如下所示:
public String getString(String key) ;
调用getString()方法,并传入上述的“httpConnector.alreadyInitialized”错误码时,会得到错误消息“HTTP connector has already been initialized”。