Spring MVC标签小结

  • Post author:
  • Post category:其他


< mvc:default-servlet-handler />的作用

在Spring MVC框架中,针对静态资源的请求处理的常见策略有两种:1. 配置< mvc:default-servlet-handler />标签,通过容器来处理;2. 配置< mvc:resources />标签,通过框架来处理。

从Spring MVC的XML Schema文件说明中可以知道,通过< mvc:default-servlet-handler />标签的配置可以使DispatcherServlet在声明过滤路径为”/”时,依旧使用容器中默认的Servlet来处理静态资源请求。在整个处理过程中,会声明注册DefaultServletHttpRequestHandler类来进行从MVC框架到容器Servlet的转发处理。

通过该处理策略弥补了Spring MVC框架对处理静态资源时的不足,可以有效提升静态资源的请求处理效率。同时又兼顾了框架对请求统一管理的需求,并能够时请求的URL命名更符合REST风格,降低人工配置请求后缀名来进行请求分类的管理成本。

DefaultServletHttpRequestHandler类的作用

在DefaultServletHttpRequestHandler类中声明了诸如Tomcat, Jetty, JBoss, GlassFish以及WebLogic, WebSphere等容器中默认Servlet的命名。在系统启动时,通过匹配容器中的RequestDispatcher类来进行注册。

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转发请求至容器处理请求。

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框架到容器的请求转发与处理。

< mvc:default-servlet-handler />的配置

除了可以通过使用DefaultServletHttpRequestHandler类中默认提供的容器,同样可以通过default-servlet-name属性来配置运行容器中默认Servlet的命名,以达到灵活配置并满足在任意Java Web容器中运行的需求。

< mvc:default-servlet-handler />的注意事项

由于在该配置下,预期是DispatcherServlet拦截的全部请求若无对应的Handler进行处理时,会转发到容器中的默认的Servlet进行处理。因此,将其他自定义的Handler中配置的URL HandlerMappings的order值小于DefaultServletHttpRequestHandler类的order值Integer.MAX_VALUE是非常重要的,以避免URL在匹配时无法满足预期。

转载于:https://my.oschina.net/u/1156626/blog/3089361