Backported DispatcherServlet and ServletContextResourcePatternResolver refinements
Issue: SPR-13011
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,8 +37,8 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* ServletContext-aware subclass of {@link PathMatchingResourcePatternResolver},
|
||||
* able to find matching resources below the web application root directory
|
||||
* via Servlet 2.3's {@code ServletContext.getResourcePaths}.
|
||||
* Falls back to the superclass' file system checking for other resources.
|
||||
* via {@link ServletContext#getResourcePaths}. Falls back to the superclass'
|
||||
* file system checking for other resources.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 1.1.2
|
||||
@@ -160,15 +160,20 @@ public class ServletContextResourcePatternResolver extends PathMatchingResourceP
|
||||
}
|
||||
try {
|
||||
JarFile jarFile = new JarFile(jarFilePath);
|
||||
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
String entryPath = entry.getName();
|
||||
if (getPathMatcher().match(entryPattern, entryPath)) {
|
||||
result.add(new UrlResource(
|
||||
ResourceUtils.URL_PROTOCOL_JAR,
|
||||
ResourceUtils.FILE_URL_PREFIX + jarFilePath + ResourceUtils.JAR_URL_SEPARATOR + entryPath));
|
||||
try {
|
||||
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
String entryPath = entry.getName();
|
||||
if (getPathMatcher().match(entryPattern, entryPath)) {
|
||||
result.add(new UrlResource(
|
||||
ResourceUtils.URL_PROTOCOL_JAR,
|
||||
ResourceUtils.FILE_URL_PREFIX + jarFilePath + ResourceUtils.JAR_URL_SEPARATOR + entryPath));
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
jarFile.close();
|
||||
}
|
||||
}
|
||||
catch (IOException ex) {
|
||||
if (logger.isWarnEnabled()) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -59,73 +59,89 @@ import org.springframework.web.util.NestedServletException;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Central dispatcher for HTTP request handlers/controllers, e.g. for web UI controllers or HTTP-based remote service
|
||||
* exporters. Dispatches to registered handlers for processing a web request, providing convenient mapping and exception
|
||||
* handling facilities.
|
||||
* Central dispatcher for HTTP request handlers/controllers, e.g. for web UI controllers
|
||||
* or HTTP-based remote service exporters. Dispatches to registered handlers for processing
|
||||
* a web request, providing convenient mapping and exception handling facilities.
|
||||
*
|
||||
* <p>This servlet is very flexible: It can be used with just about any workflow, with the installation of the
|
||||
* appropriate adapter classes. It offers the following functionality that distinguishes it from other request-driven
|
||||
* web MVC frameworks:
|
||||
* <p>This servlet is very flexible: It can be used with just about any workflow, with the
|
||||
* installation of the appropriate adapter classes. It offers the following functionality
|
||||
* that distinguishes it from other request-driven web MVC frameworks:
|
||||
*
|
||||
* <ul> <li>It is based around a JavaBeans configuration mechanism.
|
||||
* <ul>
|
||||
* <li>It is based around a JavaBeans configuration mechanism.
|
||||
*
|
||||
* <li>It can use any {@link HandlerMapping} implementation - pre-built or provided as part of an application - to
|
||||
* control the routing of requests to handler objects. Default is {@link org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping}
|
||||
* and {@link org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping}. HandlerMapping objects
|
||||
* can be defined as beans in the servlet's application context, implementing the HandlerMapping interface, overriding
|
||||
* the default HandlerMapping if present. HandlerMappings can be given any bean name (they are tested by type).
|
||||
* <li>It can use any {@link HandlerMapping} implementation - pre-built or provided as part
|
||||
* of an application - to control the routing of requests to handler objects. Default is
|
||||
* {@link org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping} and
|
||||
* {@link org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping}.
|
||||
* HandlerMapping objects can be defined as beans in the servlet's application context,
|
||||
* implementing the HandlerMapping interface, overriding the default HandlerMapping if
|
||||
* present. HandlerMappings can be given any bean name (they are tested by type).
|
||||
*
|
||||
* <li>It can use any {@link HandlerAdapter}; this allows for using any handler interface. Default adapters are {@link
|
||||
* org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter}, {@link org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter},
|
||||
* for Spring's {@link org.springframework.web.HttpRequestHandler} and {@link org.springframework.web.servlet.mvc.Controller}
|
||||
* interfaces, respectively. A default {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter}
|
||||
* will be registered as well. HandlerAdapter objects can be added as beans in the application context, overriding the
|
||||
* default HandlerAdapters. Like HandlerMappings, HandlerAdapters can be given any bean name (they are tested by type).
|
||||
* <li>It can use any {@link HandlerAdapter}; this allows for using any handler interface.
|
||||
* Default adapters are {@link org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter},
|
||||
* {@link org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter}, for Spring's
|
||||
* {@link org.springframework.web.HttpRequestHandler} and
|
||||
* {@link org.springframework.web.servlet.mvc.Controller} interfaces, respectively. A default
|
||||
* {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter}
|
||||
* will be registered as well. HandlerAdapter objects can be added as beans in the
|
||||
* application context, overriding the default HandlerAdapters. Like HandlerMappings,
|
||||
* HandlerAdapters can be given any bean name (they are tested by type).
|
||||
*
|
||||
* <li>The dispatcher's exception resolution strategy can be specified via a {@link HandlerExceptionResolver}, for
|
||||
* example mapping certain exceptions to error pages. Default are
|
||||
* <li>The dispatcher's exception resolution strategy can be specified via a
|
||||
* {@link HandlerExceptionResolver}, for example mapping certain exceptions to error pages.
|
||||
* Default are
|
||||
* {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver},
|
||||
* {@link org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver}, and
|
||||
* {@link org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver}. These HandlerExceptionResolvers can be overridden
|
||||
* through the application context. HandlerExceptionResolver can be given any bean name (they are tested by type).
|
||||
* {@link org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver}.
|
||||
* These HandlerExceptionResolvers can be overridden through the application context.
|
||||
* HandlerExceptionResolver can be given any bean name (they are tested by type).
|
||||
*
|
||||
* <li>Its view resolution strategy can be specified via a {@link ViewResolver} implementation, resolving symbolic view
|
||||
* names into View objects. Default is {@link org.springframework.web.servlet.view.InternalResourceViewResolver}.
|
||||
* ViewResolver objects can be added as beans in the application context, overriding the default ViewResolver.
|
||||
* ViewResolvers can be given any bean name (they are tested by type).
|
||||
* <li>Its view resolution strategy can be specified via a {@link ViewResolver}
|
||||
* implementation, resolving symbolic view names into View objects. Default is
|
||||
* {@link org.springframework.web.servlet.view.InternalResourceViewResolver}.
|
||||
* ViewResolver objects can be added as beans in the application context, overriding the
|
||||
* default ViewResolver. ViewResolvers can be given any bean name (they are tested by type).
|
||||
*
|
||||
* <li>If a {@link View} or view name is not supplied by the user, then the configured {@link
|
||||
* RequestToViewNameTranslator} will translate the current request into a view name. The corresponding bean name is
|
||||
* "viewNameTranslator"; the default is {@link org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator}.
|
||||
* <li>If a {@link View} or view name is not supplied by the user, then the configured
|
||||
* {@link RequestToViewNameTranslator} will translate the current request into a view name.
|
||||
* The corresponding bean name is "viewNameTranslator"; the default is
|
||||
* {@link org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator}.
|
||||
*
|
||||
* <li>The dispatcher's strategy for resolving multipart requests is determined by a {@link
|
||||
* org.springframework.web.multipart.MultipartResolver} implementation. Implementations for Jakarta Commons FileUpload
|
||||
* and Jason Hunter's COS are included; the typical choise is {@link org.springframework.web.multipart.commons.CommonsMultipartResolver}.
|
||||
* <li>The dispatcher's strategy for resolving multipart requests is determined by a
|
||||
* {@link org.springframework.web.multipart.MultipartResolver} implementation.
|
||||
* Implementations for Apache Commons FileUpload and Servlet 3 are included; the typical
|
||||
* choice is {@link org.springframework.web.multipart.commons.CommonsMultipartResolver}.
|
||||
* The MultipartResolver bean name is "multipartResolver"; default is none.
|
||||
*
|
||||
* <li>Its locale resolution strategy is determined by a {@link LocaleResolver}. Out-of-the-box implementations work via
|
||||
* HTTP accept header, cookie, or session. The LocaleResolver bean name is "localeResolver"; default is {@link
|
||||
* org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver}.
|
||||
* <li>Its locale resolution strategy is determined by a {@link LocaleResolver}.
|
||||
* Out-of-the-box implementations work via HTTP accept header, cookie, or session.
|
||||
* The LocaleResolver bean name is "localeResolver"; default is
|
||||
* {@link org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver}.
|
||||
*
|
||||
* <li>Its theme resolution strategy is determined by a {@link ThemeResolver}. Implementations for a fixed theme and for
|
||||
* cookie and session storage are included. The ThemeResolver bean name is "themeResolver"; default is {@link
|
||||
* org.springframework.web.servlet.theme.FixedThemeResolver}. </ul>
|
||||
* <li>Its theme resolution strategy is determined by a {@link ThemeResolver}.
|
||||
* Implementations for a fixed theme and for cookie and session storage are included.
|
||||
* The ThemeResolver bean name is "themeResolver"; default is
|
||||
* {@link org.springframework.web.servlet.theme.FixedThemeResolver}.
|
||||
* </ul>
|
||||
*
|
||||
* <p><b>NOTE: The {@code @RequestMapping} annotation will only be processed if a corresponding
|
||||
* {@code HandlerMapping} (for type level annotations) and/or {@code HandlerAdapter} (for method level
|
||||
* annotations) is present in the dispatcher.</b> This is the case by default. However, if you are defining custom
|
||||
* {@code HandlerMappings} or {@code HandlerAdapters}, then you need to make sure that a corresponding custom
|
||||
* {@code DefaultAnnotationHandlerMapping} and/or {@code AnnotationMethodHandlerAdapter} is defined as well -
|
||||
* provided that you intend to use {@code @RequestMapping}.
|
||||
* <p><b>NOTE: The {@code @RequestMapping} annotation will only be processed if a
|
||||
* corresponding {@code HandlerMapping} (for type-level annotations) and/or
|
||||
* {@code HandlerAdapter} (for method-level annotations) is present in the dispatcher.</b>
|
||||
* This is the case by default. However, if you are defining custom {@code HandlerMappings}
|
||||
* or {@code HandlerAdapters}, then you need to make sure that a corresponding custom
|
||||
* {@code DefaultAnnotationHandlerMapping} and/or {@code AnnotationMethodHandlerAdapter}
|
||||
* is defined as well - provided that you intend to use {@code @RequestMapping}.
|
||||
*
|
||||
* <p><b>A web application can define any number of DispatcherServlets.</b> Each servlet will operate in its own
|
||||
* namespace, loading its own application context with mappings, handlers, etc. Only the root application context as
|
||||
* loaded by {@link org.springframework.web.context.ContextLoaderListener}, if any, will be shared.
|
||||
* <p><b>A web application can define any number of DispatcherServlets.</b>
|
||||
* Each servlet will operate in its own namespace, loading its own application context
|
||||
* with mappings, handlers, etc. Only the root application context as loaded by
|
||||
* {@link org.springframework.web.context.ContextLoaderListener}, if any, will be shared.
|
||||
*
|
||||
* <p>As of Spring 3.1, {@code DispatcherServlet} may now be injected with a web
|
||||
* application context, rather than creating its own internally. This is useful in Servlet
|
||||
* 3.0+ environments, which support programmatic registration of servlet instances. See
|
||||
* {@link #DispatcherServlet(WebApplicationContext)} Javadoc for details.
|
||||
* 3.0+ environments, which support programmatic registration of servlet instances.
|
||||
* See the {@link #DispatcherServlet(WebApplicationContext)} javadoc for details.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Juergen Hoeller
|
||||
@@ -851,12 +867,11 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
doDispatch(request, response);
|
||||
}
|
||||
finally {
|
||||
if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
|
||||
return;
|
||||
}
|
||||
// Restore the original attribute snapshot, in case of an include.
|
||||
if (attributesSnapshot != null) {
|
||||
restoreAttributesAfterInclude(request, attributesSnapshot);
|
||||
if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
|
||||
// Restore the original attribute snapshot, in case of an include.
|
||||
if (attributesSnapshot != null) {
|
||||
restoreAttributesAfterInclude(request, attributesSnapshot);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -885,7 +900,7 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
|
||||
try {
|
||||
processedRequest = checkMultipart(request);
|
||||
multipartRequestParsed = processedRequest != request;
|
||||
multipartRequestParsed = (processedRequest != request);
|
||||
|
||||
// Determine handler for the current request.
|
||||
mappedHandler = getHandler(processedRequest, false);
|
||||
@@ -914,14 +929,11 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Actually invoke the handler.
|
||||
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
|
||||
}
|
||||
finally {
|
||||
if (asyncManager.isConcurrentHandlingStarted()) {
|
||||
return;
|
||||
}
|
||||
// Actually invoke the handler.
|
||||
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
|
||||
|
||||
if (asyncManager.isConcurrentHandlingStarted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyDefaultViewName(request, mv);
|
||||
@@ -941,12 +953,15 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
finally {
|
||||
if (asyncManager.isConcurrentHandlingStarted()) {
|
||||
// Instead of postHandle and afterCompletion
|
||||
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
|
||||
return;
|
||||
if (mappedHandler != null) {
|
||||
mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
|
||||
}
|
||||
}
|
||||
// Clean up any resources used by a multipart request.
|
||||
if (multipartRequestParsed) {
|
||||
cleanupMultipart(processedRequest);
|
||||
else {
|
||||
// Clean up any resources used by a multipart request.
|
||||
if (multipartRequestParsed) {
|
||||
cleanupMultipart(processedRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1255,7 +1270,7 @@ public class DispatcherServlet extends FrameworkServlet {
|
||||
}
|
||||
|
||||
private void triggerAfterCompletionWithError(HttpServletRequest request, HttpServletResponse response,
|
||||
HandlerExecutionChain mappedHandler, Error error) throws Exception, ServletException {
|
||||
HandlerExecutionChain mappedHandler, Error error) throws Exception {
|
||||
|
||||
ServletException ex = new NestedServletException("Handler processing failed", error);
|
||||
if (mappedHandler != null) {
|
||||
|
||||
Reference in New Issue
Block a user