在Spring MVC框架中,針對靜態資源的請求處理的常見策略有兩種:1. 配置< mvc:default-servlet-handler />標籤,經過容器來處理;2. 配置< mvc:resources />標籤,經過框架來處理。mvc
從Spring MVC的XML Schema文件說明中能夠知道,經過< mvc:default-servlet-handler />標籤的配置能夠使DispatcherServlet在聲明過濾路徑爲"/"時,依舊使用容器中默認的Servlet來處理靜態資源請求。在整個處理過程當中,會聲明註冊DefaultServletHttpRequestHandler類來進行從MVC框架到容器Servlet的轉發處理。app
經過該處理策略彌補了Spring MVC框架對處理靜態資源時的不足,能夠有效提高靜態資源的請求處理效率。同時又兼顧了框架對請求統一管理的需求,並可以時請求的URL命名更符合REST風格,下降人工配置請求後綴名來進行請求分類的管理成本。框架
在DefaultServletHttpRequestHandler類中聲明瞭諸如Tomcat, Jetty, JBoss, GlassFish以及WebLogic, WebSphere等容器中默認Servlet的命名。在系統啓動時,經過匹配容器中的RequestDispatcher類來進行註冊。this
public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; if (!StringUtils.hasText(this.defaultServletName)) { if (this.servletContext.getNamedDispatcher(COMMON_DEFAULT_SERVLET_NAME) != null) { this.defaultServletName = COMMON_DEFAULT_SERVLET_NAME; } else if (this.servletContext.getNamedDispatcher(GAE_DEFAULT_SERVLET_NAME) != null) { this.defaultServletName = GAE_DEFAULT_SERVLET_NAME; } else if (this.servletContext.getNamedDispatcher(RESIN_DEFAULT_SERVLET_NAME) != null) { this.defaultServletName = RESIN_DEFAULT_SERVLET_NAME; } else if (this.servletContext.getNamedDispatcher(WEBLOGIC_DEFAULT_SERVLET_NAME) != null) { this.defaultServletName = WEBLOGIC_DEFAULT_SERVLET_NAME; } else if (this.servletContext.getNamedDispatcher(WEBSPHERE_DEFAULT_SERVLET_NAME) != null) { this.defaultServletName = WEBSPHERE_DEFAULT_SERVLET_NAME; } else { throw new IllegalStateException("Unable to locate the default servlet for serving static content. " + "Please set the 'defaultServletName' property explicitly."); } } }
當請求抵達該Handler類時會直接調用對應的RequestDispatcher來forward轉發請求至容器處理請求。spa
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName); if (rd == null) { throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" + this.defaultServletName + "'"); } rd.forward(request, response); }
由此完成從MVC框架到容器的請求轉發與處理。code
除了能夠經過使用DefaultServletHttpRequestHandler類中默認提供的容器,一樣能夠經過default-servlet-name屬性來配置運行容器中默認Servlet的命名,以達到靈活配置並知足在任意Java Web容器中運行的需求。ci
因爲在該配置下,預期是DispatcherServlet攔截的所有請求若無對應的Handler進行處理時,會轉發到容器中的默認的Servlet進行處理。所以,將其餘自定義的Handler中配置的URL HandlerMappings的order值小於DefaultServletHttpRequestHandler類的order值Integer.MAX_VALUE是很是重要的,以免URL在匹配時沒法知足預期。資源