001/* 002 * Copyright 2002-2015 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.servlet.resource; 018 019import java.io.IOException; 020import javax.servlet.RequestDispatcher; 021import javax.servlet.ServletContext; 022import javax.servlet.ServletException; 023import javax.servlet.http.HttpServletRequest; 024import javax.servlet.http.HttpServletResponse; 025 026import org.springframework.util.StringUtils; 027import org.springframework.web.HttpRequestHandler; 028import org.springframework.web.context.ServletContextAware; 029 030/** 031 * An {@link HttpRequestHandler} for serving static files using the Servlet container's "default" Servlet. 032 * 033 * <p>This handler is intended to be used with a "/*" mapping when the 034 * {@link org.springframework.web.servlet.DispatcherServlet DispatcherServlet} 035 * is mapped to "/", thus overriding the Servlet container's default handling of static resources. 036 * The mapping to this handler should generally be ordered as the last in the chain so that it will 037 * only execute when no other more specific mappings (i.e., to controllers) can be matched. 038 * 039 * <p>Requests are handled by forwarding through the {@link RequestDispatcher} obtained via the 040 * name specified through the {@link #setDefaultServletName "defaultServletName" property}. 041 * In most cases, the {@code defaultServletName} does not need to be set explicitly, as the 042 * handler checks at initialization time for the presence of the default Servlet of well-known 043 * containers such as Tomcat, Jetty, Resin, WebLogic and WebSphere. However, when running in a 044 * container where the default Servlet's name is not known, or where it has been customized 045 * via server configuration, the {@code defaultServletName} will need to be set explicitly. 046 * 047 * @author Jeremy Grelle 048 * @author Juergen Hoeller 049 * @since 3.0.4 050 */ 051public class DefaultServletHttpRequestHandler implements HttpRequestHandler, ServletContextAware { 052 053 /** Default Servlet name used by Tomcat, Jetty, JBoss, and GlassFish */ 054 private static final String COMMON_DEFAULT_SERVLET_NAME = "default"; 055 056 /** Default Servlet name used by Google App Engine */ 057 private static final String GAE_DEFAULT_SERVLET_NAME = "_ah_default"; 058 059 /** Default Servlet name used by Resin */ 060 private static final String RESIN_DEFAULT_SERVLET_NAME = "resin-file"; 061 062 /** Default Servlet name used by WebLogic */ 063 private static final String WEBLOGIC_DEFAULT_SERVLET_NAME = "FileServlet"; 064 065 /** Default Servlet name used by WebSphere */ 066 private static final String WEBSPHERE_DEFAULT_SERVLET_NAME = "SimpleFileServlet"; 067 068 069 private String defaultServletName; 070 071 private ServletContext servletContext; 072 073 074 /** 075 * Set the name of the default Servlet to be forwarded to for static resource requests. 076 */ 077 public void setDefaultServletName(String defaultServletName) { 078 this.defaultServletName = defaultServletName; 079 } 080 081 /** 082 * If the {@code defaultServletName} property has not been explicitly set, 083 * attempts to locate the default Servlet using the known common 084 * container-specific names. 085 */ 086 @Override 087 public void setServletContext(ServletContext servletContext) { 088 this.servletContext = servletContext; 089 if (!StringUtils.hasText(this.defaultServletName)) { 090 if (this.servletContext.getNamedDispatcher(COMMON_DEFAULT_SERVLET_NAME) != null) { 091 this.defaultServletName = COMMON_DEFAULT_SERVLET_NAME; 092 } 093 else if (this.servletContext.getNamedDispatcher(GAE_DEFAULT_SERVLET_NAME) != null) { 094 this.defaultServletName = GAE_DEFAULT_SERVLET_NAME; 095 } 096 else if (this.servletContext.getNamedDispatcher(RESIN_DEFAULT_SERVLET_NAME) != null) { 097 this.defaultServletName = RESIN_DEFAULT_SERVLET_NAME; 098 } 099 else if (this.servletContext.getNamedDispatcher(WEBLOGIC_DEFAULT_SERVLET_NAME) != null) { 100 this.defaultServletName = WEBLOGIC_DEFAULT_SERVLET_NAME; 101 } 102 else if (this.servletContext.getNamedDispatcher(WEBSPHERE_DEFAULT_SERVLET_NAME) != null) { 103 this.defaultServletName = WEBSPHERE_DEFAULT_SERVLET_NAME; 104 } 105 else { 106 throw new IllegalStateException("Unable to locate the default servlet for serving static content. " + 107 "Please set the 'defaultServletName' property explicitly."); 108 } 109 } 110 } 111 112 113 @Override 114 public void handleRequest(HttpServletRequest request, HttpServletResponse response) 115 throws ServletException, IOException { 116 117 RequestDispatcher rd = this.servletContext.getNamedDispatcher(this.defaultServletName); 118 if (rd == null) { 119 throw new IllegalStateException("A RequestDispatcher could not be located for the default servlet '" + 120 this.defaultServletName + "'"); 121 } 122 rd.forward(request, response); 123 } 124 125}