除了以上的新特性之外,ServletContext對象的功能在新版本中也得到了增強。現在,該對象支持在運行時動態部署Servlet、過濾器、監聽器,以及為Servlet和過濾器增加URL映射等。以Servlet為例,過濾器與監聽器與之類似。ServletContext為動態配置Servlet增加了如下方法:
◆ServletRegistration.DynamicaddServlet(StringservletName,Class<?extendsServlet>servletClass)
◆ServletRegistration.DynamicaddServlet(StringservletName,Servletservlet)
◆ServletRegistration.DynamicaddServlet(StringservletName,StringclassName)
◆<TextendsServlet>TcreateServlet(Class<T>clazz)
◆ServletRegistrationgetServletRegistration(StringservletName)
◆Map<String,?extendsServletRegistration>getServletRegistrations()
其中前三個方法的作用是相同的,只是參數類型不同而已;通過createServlet()方法創建的Servlet,通常需要做一些自定義的配置,然後使用addServlet()方法來將其動態注冊為一個可以用於服務的Servlet。
兩個getServletRegistration()方法主要用於動態為Servlet增加映射信息,這等價於在web.xml(抑或web-fragment.XML)中使用<servlet-mapping>標簽為存在的Servlet增加映射信息。以上ServletContext新增的方法要麼是在ServletContextListener的contexInitialized方法中調用,要麼是在ServletContainerInitializer的onStartup()方法中調用。
ServletContainerInitializer也是Servlet3.0新增的一個接口,容器在啟動時使用JAR服務API(JARServiceAPI)來發現ServletContainerInitializer的實現類,並且容器將WEB-INF/lib目錄下JAR包中的類都交給該類的onStartup()方法處理,我們通常需要在該實現類上使用@HandlesTypes注解來指定希望被處理的類,過濾掉不希望給onStartup()處理的類。
HttpServletRequest對文件上傳的支持
此前,對於處理上傳文件的操作一直是讓開發者頭疼的問題,因為Servlet本身沒有對此提供直接的支持,需要使用第三方框架來實現,而且使用起來也不夠簡單。如今這都成為了歷史,Servlet 3.0已經提供了這個功能,而且使用也非常簡單。為此,HttpServletRequest提供了兩個方法用於從請求中解析出上傳的文件:
◆PartgetPart(Stringname)
◆Collection<Part>getParts()
前者用於獲取請求中給定name的文件,後者用於獲取所有的文件。每一個文件用一個Javax.servlet.http.Part對象來表示。該接口提供了處理文件的簡易方法,比如write()、delete()等。至此,結合HttpServletRequest和Part來保存上傳的文件變得非常簡單,如下所示:
◆Partphoto=request.getPart("photo");
◆photo.write("/tmp/photo.jpg");
可以將兩行代碼簡化為request.getPart("photo").write("/tmp/photo.jpg")一行。另外,開發者可以配合前面提到的@MultipartConfig注解來對上傳操作進行一些自定義的配置,比如限制上傳文件的大小,以及保存文件的路徑等。其用法非常簡單,故不在此贅述了。需要注意的是,如果請求的MIME類型不是multipart/form-data,則不能使用上面的兩個方法,否則將拋異常。
總結
Servlet 3.0的眾多新特性使得Servlet開發變得更加簡單,尤其是異步處理特性和可插性支持的出現,必將對現有的MVC框架產生深遠影響。雖然我們通常不會自己去用Servlet編寫控制層代碼,但是也許在下一個版本的Struts中,您就能切實感受到這些新特性帶來的實質性改變。