Application?2?
第一個應用程序里存在一個值得注意的問題。?在ServletProcessor1?類的?process?方法里,上溯?(upcast)ex02.pyrmont.Request?實例到?javax.servlet.ServletRequest,將其作為第一個參數傳遞給?servlet?的?service?方法。另上溯(upcast)?ex02.pyrmont.Response?實例到?javax.servlet.ServletResponse?,并將其作為第二個參數傳遞給?servlet?的?service?方法。?
try?{
???servlet?=?(Servlet)?myClass.newInstance();
???servlet.service((ServletRequest)?request,?(ServletResponse)?response);
}這樣會使安全性能大打折扣。?知道?servlet?容器工作原理的程序員可以將?ServletRequest?和?ServletResponse?實例向下轉型?(downcast)?到Request?和?Response?,并調用它們的?public?方法。?Request?實例能調用它的?parse?方法;?Request?實例能調用它的?sendStaticResource?方法。?
可以將?parse?和?sendStaticResource?方法設為?private,因為在?ex02.pyrmont?里將會從其他類里調用它們。?然而,這兩個方法在?servlet?內應該是不可用的。?一個解決方法是:給?Request?和?Response?類一個默認的訪問修飾符,以致他們在?ex02.pyrmont?外不能被使用。?但還有一個更好的解決方法:?使用?facade?類。?
在第二個應用程序內,添加兩個?facade?類:RequestFacade?和?ResponseFacade。?RequestFacade?類實現?ServletRequest?接口,并通過傳遞?Request?實例來實例化,?Request?實例將在?ServletRequest?對象的構建器里被引用?。?ServletRequest?對象本身是?private?類型的,不能在類之外訪問。就構建?RequestFacade?對象,并將其傳遞給?service?方法,而不上溯?(upcast)?Request?對象給?ServletRequest,并將其傳遞給?service?方法。?servlet?程序員仍舊可以向下轉型?(downcast)?ServletRequest?到?RequestFacade,但是,只要訪問?ServletRequest?接口的可用方法就可以了。現在,parseUri?就安全了。?
Listing?2.5?顯示?RequestFacade?類部分代碼:?
Listing?2.5.?RequestFacade?類?
package?ex02.pyrmont;
public?class?RequestFacade?implements?ServletRequest?{
????private?ServletRequest?request?=?null;
????public?RequestFacade(Request?request)?{
????????this.request?=?request;
????}????/*?implementation?of?the?ServletRequest*/
????public?Object?getAttribute(String?attribute)?{
????????return?request.getAttribute(attribute);
????}
????public?Enumeration?getAttributeNames()?{
????????return?request.getAttributeNames();
????}
????...
}注意?RequestFacade?構造函數。?它會接受一個?Request?對象,即刻分配給私有的?servletRequest?對象引用。?還要注意,RequestFacade?內的每個方法調用?ServletRequest?對象內相應的方法。?
ResponseFacade?類也是如此。?
以下是?application?2?所包含的類?
HttpServer2
Request?
Response?
StaticResourceProcessor?
ServletProcessor2?
Constants?HttpServer2?類類似于?HttpServer1,
只是它在?await?方法內使用了?ServletProcessor2?而不是ServletProcessor1。
if?(request.getUri().startsWith("/servlet/"))?{
???ServletProcessor2?processor?=?new?ServletProcessor2();
???processor.process(request,?response);
}else?{
????...
??????}
ServletProcessor2?類也類似于?ServletProcessor1,
只是在以下?process?方法的部分代碼有點不同:
Servlet?servlet?=?null;
RequestFacade?requestFacade???=?new?RequestFacade(request);
ResponseFacade?responseFacade?=?new?ResponseFacade(response);
try?{
????servlet?=?(Servlet)?myClass.newInstance();
????servlet.service((ServletRequest)?requestFacade,(ServletResponse)?responseFacade);
}編譯并運行該應用程序?
如果要編譯該應用程序,在工作目錄下鍵入以下命令:?
javac?-d?.?-classpath?./lib/servlet.jar?src/ex02/pyrmont/*.java?如果要在?windows?下運行該應用程序,在工作目錄下鍵入以下命令:?
java-classpath?./lib/servlet.jar;./?ex02.pyrmont.HttpServer2?在linux環境下,使用分號來隔開類庫:?
java?-classpath?./lib/servlet.jar:./?ex02.pyrmont.HttpServer2?您可以使用和?application?1?相同的?URL?以收到同樣的結果。?
總結?
本文討論了簡單的能夠用于服務靜態資源,以及處理如?PrimitiveServlet?一樣簡單的?servlet?的?servlet?容器。?同時也提供?javax.servlet.Servlet?的背景信息。?
posted on 2006-12-06 12:40
matthew 閱讀(350)
評論(0) 編輯 收藏 所屬分類:
JavaEE