DefaultServletHttpRequestHandler
是Spring MVC
提供的使用Servlet
容器缺省Servlet
处理静态文件的HttpRequestHandler
实现。
因为Spring MVC
可以支持多种Servlet
容器,比如Tomat
,Jetty
,JBoss
,GlassFish
,Resin
,GAE
,WebLogic
,WebSphere
等。而在这些容器中,缺省Servlet
的名字又不尽相同。所以该HttpRequestHandler
会运行时检测ServletContext
所对应的Servlet
容器的类型,从而确保无论使用哪种Servlet
容器,它总是能够正确地获取到缺省Servlet
并转发相应的静态文件处理请求。
实际上
Spring MVC
提供了自己处理静态资源文件的机制,无论是classpath
上的静态资源文件,还是文件系统中的静态资源文件,Spring MVC
都有自己的处理机制。DefaultServletHttpRequestHandler
的作用,主要是用在这些机制未被配置,或者开发人员主动希望通过Servlet
容器缺省Servlet
处理静态资源文件的情形。
源代码
package org.springframework.web.servlet.resource;
public class DefaultServletHttpRequestHandler implements HttpRequestHandler, ServletContextAware {
/** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish. */
private static final String COMMON_DEFAULT_SERVLET_NAME = "default";
/** Default Servlet name used by Google App Engine. */
private static final String GAE_DEFAULT_SERVLET_NAME = "_ah_default";
/** Default Servlet name used by Resin. */
private static final String RESIN_DEFAULT_SERVLET_NAME = "resin-file";
/** Default Servlet name used by WebLogic. */
private static final String WEBLOGIC_DEFAULT_SERVLET_NAME = "FileServlet";
/** Default Servlet name used by WebSphere. */
private static final String WEBSPHERE_DEFAULT_SERVLET_NAME = "SimpleFileServlet";
@Nullable
private String defaultServletName;
@Nullable
private ServletContext servletContext;
/**
* Set the name of the default Servlet to be forwarded to for static resource requests.
*/
public void setDefaultServletName(String defaultServletName) {
this.defaultServletName = defaultServletName;
}
/**
* If the {@code defaultServletName} property has not been explicitly set,
* attempts to locate the default Servlet using the known common
* container-specific names.
*/
@Override
public void setServletContext(ServletContext servletContext) {
// 在ServletContext设置时猜测Servlet容器缺省的Servlet名称是什么并记录到 this.defaultServletName
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.");
}
}
}
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Assert.state(this.servletContext != null, "No ServletContext set");
// 获取到Servlet容器缺省Servlet的 RequestDispatcher,将请求转发给它处理。
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);
}
}