組態方式


在 Servlet 3.0 中,要為 Web 應用程式進行 Servlet、過濾器、傾聽器的組態設定有幾種方式:

  • 透過 @WebServlet@WebFilter@WebListener 等標註的設定。
  • 透過 web.xml 的設定,如果 web.xml 中設定的 Servlet、過濾器等類別中已包括標註,則以 web.xml 中的設定為主。
  • 在容器初始化時,透過 ServletContextaddServlet()addFilter()addListener() 等方法來設定,這可以實作在 ServletContextListenercontextInitialized() 中,或者是 ServletContainerInitializeronStartup() 中實作。

第三種方式以 Servlet 為例,ServletContext 上所新增的相關方法有:

  • ServletRegistration.Dynamic addServlet(java.lang.String servletName, java.lang.Class<? extends Servlet> servletClass)
  • ServletRegistration.Dynamic addServlet(java.lang.String servletName, Servlet servlet)
  • ServletRegistration.Dynamic addServlet(java.lang.String servletName, java.lang.String className)
  • <T extends Servlet> T createServlet(java.lang.Class<T> clazz) throws ServletException
  • ServletRegistration getServletRegistration(java.lang.String servletName)
  • java.util.Map<java.lang.String,? extends ServletRegistration> getServletRegistrations()

ServletRegistrationgetMappings()addMapping() 可以取得或增加 Servlet 的對應(Mapping)訊息,也就是相當於 web.xml 中 <servlet-mapping> 的資訊。

在一個 JAR 檔案中如果有個 META-INF/services/javax.servlet.ServletContainerInitializer 檔案,該檔案是個文件檔案,當中所撰寫的類別名稱若實作了 ServletContainerInitializer 介面,則在容器啟動時,將會載入這些類別並執行其 onStartup() 方法:

..
@HandlesTypes({OOO.class, XXX.class}) 
void onStartup(java.util.Set<java.lang.Class<?>> c, ServletContext ctx)
               throws ServletException {
   ...
}
...

其中 @HandlesTypes 中指定的類別,將傳入給 onStartup() 的第一個參數,以便在 onStartup() 中處理。

如果要決定 Servlet、過濾器、傾聽器的載入順序,則一定要在 web.xml 中設定,載入的順序就是其在 web.xml 中宣告的順序(Servlet 的話,就是 load-on-startup 值一樣時的情況)。

實際上,在 Servlet 3.0 中支援對 Servlet、過濾器、傾聽器抽換性(pluggability),可以藉由在 JAR 中包括符合要求的文件,就可以達到置換 JAR 檔案即抽換 Servlet、過濾器、傾聽器的目的,這之後會再說明。