應用程式1中有一個嚴重的問題。在servletprocessor1類的process()方法中,必須将ex02.pyrmont.request的執行個體向上轉型為javax.servlet.servletrequest執行個體,将ex02.pyrmont.response執行個體向上轉型為javax.servlet.servletresponse執行個體,然後将它們作為參數傳遞給servlet的service()方法:
這是不安全的做法,了解這個servlet容器内部工作原理的servlet程式員可以将servletrequest執行個體和servletresponse執行個體分别向下轉型為ex02.pyrmont.request執行個體和ex02.pyrmont.response執行個體,就可以調用它們各自的公共方法了。有了request執行個體後,就可以調用其parse()方法;而有了response執行個體後,就可以調用其sendstaticresource()方法。
不能将parse()方法和sendstaticresource()方法設定為私有方法,因為它們會被其他的類調用,但是這兩個方法在servlet中不應該是可用的,是以這個方法不好。一種解決方法是将request類和response類都設為預設的通路修飾符,這樣就不能從ex02.pyrmont包外對它們進行通路了。但是,這裡有一個更完美的方法:使用外觀類。uml 關系圖如圖2-2所示。
在第2個應用程式中,添加了兩個外觀類:requestfacade和responsefacade。requestfacade類實作servletrequest接口,在其構造函數中需要把它指定的一個reuqest對象傳遞給servletrequest對象引用。servletrequest接口中每個方法的實作都會調用request對象的相應方法。但是,servletrequest對象本身是私有的,無法從類的外部進行通路。相比于将request對象向上轉型為servletrequest對象,并将其傳給service()方法,這裡會建立一個requestfacade對象,再将其傳遞給service()方法。servlet程式員仍然可以将servletrequest執行個體向下轉型為requestfacade對象,但它們隻能通路servletrequest接口中提供的方法。現在parse()方法和geturi()方法是安全的了。
代碼清單2-7給出了requestfacade類的定義。
注意requestfacade類的構造函數,它接受一個request對象,但立即将其賦給私有的servletrequest對象引用。還要注意的是,requestfacade中的每個方法會調用servletrequest對象中相對應的方法來執行。
responsefacade類的情況與此相同。
應用程式2中共需要使用6個類:
httpserver2
request
response
staticresourceprocessor
servletprocessor2
constants
httpserver2類與httpserver1類相似,隻是在其await()方法中它會使用servletprocessor2類,而不是servletprocessor1類:
servletprocessor2類與servletprocessor1類相似,隻是在其process()方法的以下部分中有些許不同:
運作應用程式
要在windows平台上運作該程式,可以在工作目錄下執行如下指令:
在linux平台上,需要用冒号分割兩個庫檔案:
可以使用與應用程式1相同的url來測試,結果是相同的。