在前面的文章中提到,Catalina中有两个模块:连接器和容器。下面将实现一个创建更好的请求和相应对象的连接器,用来改进上文简易版基于Java的Servlet容器实现。
连接器的详细工作:连接器解析HTTP请求头部并然servlet可以获得头部,cookies, 参数名/值等等。你将会完善第2章中Response类的getWriter方法。在介绍StringManager类之前有必要介绍org.apache.catalina.util里面的StringManager类。与简易版基于Java的Servlet容器实现中实现方式不同HttpServer类被分离为两类:HttpConnector和HttpProcessor。HttpConnector实例处理HTTP请求,HttpProcessor实例负责创建请求和响应对象。
StringManager类
一个像Tomcat这样的大型应用需要仔细的处理错误信息。Tomcat所采用的方法是在一个属性文件里边存储错误信息,这样,可以容易的修改这些信息。不过,Tomcat中有数以百计的类。把所有类使用的错误信息存储到一个大的属性文件里面将会产生维护的噩梦。因此,Tomcat为每个包都分配一个属性文件。例如,在包org.apache.catalina.connector里边的属性文件包含了该包所有的类抛出的所有错误信息。每个属性文件都会被一个org.apache.catalina.util.StringManager类的实例所处理。StringManager为单例模式,每个包由一个实例来实现每个实例存储在一个以报名为键(key)的Hashtable中。
源文件如下:
package com.vipshop.test.ext03.util;
import java.text.MessageFormat;
import java.util.Hashtable;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
public class StringManager {
private ResourceBundle bundle;
private static Hashtable<Object, Object> managers = new Hashtable<Object, Object>();
private StringManager(String packageName) {
String bundleName = packageName + ".LocalStrings";
this.bundle = ResourceBundle.getBundle(bundleName);
}
public synchronized static StringManager getManager(String packageName) {
StringManager mgr = (StringManager)managers.get(packageName);
if (mgr == null) {
mgr = new StringManager(packageName);
managers.put(packageName, mgr);
}
return mgr;
}
/**
* Get a string from the underlying resource bundle.
*
* @param key
* @return
*/
public String getString(String key) {
if (key == null) {
String msg = "key is null";
throw new NullPointerException(msg);
}
String str = null;
try {
str = bundle.getString(key);
} catch (MissingResourceException e) {
str = "Cannot find message associated with key '" + key + "'";
e.printStackTrace();
}
return str;
}
/**
* Get a string from the underlying resource bundle and format
* it with the given set of arguments
*
* @param key
* @param args
* @return
*/
public String getString(String key, Object[] args) {
String iString = null;
String value = getString(key);
try {
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";
}
}
iString = MessageFormat.format(value, nonNullArgs);
}
} catch (IllegalArgumentException e) {
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;
}
/**
* Get a string from the underlying resource bundle and format it with the given object argument.
* This argument can of course be a String object.
*
* @param key
* @param arg
* @return
*/
public String getString(String key, Object arg) {
Object[] args = new Object[] {arg};
return getString(key, args);
}
/**
* Get a string from the underlying resource bundle and format it with the given object
* arguments. These arguments can of cource be String objects.
*
* @param key
* @param arg1
* @param arg2
* @return
*/
public String getString(String key, Object arg1, Object arg2) {
Object[] args = new Object[] {arg1, arg2};
return getString(key, args);
}
/**
* Get a string from the underlying resource bundle and format it with the given object arguments.
* These arguments can of course be String objects.
*
* @param key
* @param arg1
* @param arg2
* @param arg3
* @return
*/
public String getString(String key, Object arg1, Object arg2, Object arg3) {
Object[] args = new Object[] {arg1, arg2, arg3};
return getString(key, args);
}
/**
* Get a string from the underlying resource bundle and format it with the given object arguments.These arguments can
* of course be String objects.
*
* @param key
* @param arg1
* @param arg2
* @param arg3
* @param arg4
* @return
*/
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);
}
}
未完待续!