diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java index 9cd1822f83..1fdaa0e22d 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java @@ -464,9 +464,14 @@ public abstract class WebMvcConfigurationSupport implements ApplicationContextAw } /** - * Returns a {@link HandlerExceptionResolverComposite} that contains a list - * of exception resolvers. To customize the list of exception resolvers, - * consider overriding {@link #configureHandlerExceptionResolvers(List)}. + * Returns a {@link HandlerExceptionResolverComposite} containing a list + * of exception resolvers obtained either through + * {@link #configureHandlerExceptionResolvers(List)} or through + * {@link #addDefaultHandlerExceptionResolvers(List)}. + *

Note: This method cannot be made final due to CGLib + * constraints. Rather than overriding it, consider overriding + * {@link #configureHandlerExceptionResolvers(List)}, which allows + * providing a list of resolvers. */ @Bean public HandlerExceptionResolver handlerExceptionResolver() throws Exception { diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/RequestContext.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/RequestContext.java index 68267acf20..97aa563b90 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/RequestContext.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/support/RequestContext.java @@ -417,6 +417,21 @@ public class RequestContext { return url; } + /** + * Return the path to URL mappings within the current servlet including the + * context path and the servlet path of the original request. This is useful + * for building links to other resources within the application where a + * servlet mapping of the style {@code "/main/*"} is used. + *

Delegates to the UrlPathHelper for decoding the context path. + * @see javax.servlet.http.HttpServletRequest#getContextPath + * @see javax.servlet.http.HttpServletRequest#getServletPath() + * @see #getUrlPathHelper + */ + public String getPathToServlet() { + return this.urlPathHelper.getOriginatingContextPath(this.request) + + this.urlPathHelper.getOriginatingServletPath(this.request); + } + /** * Return the request URI of the original request, that is, the invoked URL without parameters. This is particularly * useful as HTML form action target, possibly in combination with the original query string.

Note this diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/RequestContextTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/RequestContextTests.java index a27b99e8fd..195f06423c 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/RequestContextTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/support/RequestContextTests.java @@ -27,12 +27,13 @@ import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockServletContext; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.GenericWebApplicationContext; +import org.springframework.web.util.WebUtils; import static org.junit.Assert.*; /** * @author Dave Syer - * + * @author Rossen Stoyanchev */ public class RequestContextTests { @@ -51,14 +52,14 @@ public class RequestContextTests { } @Test - public void testGetContextUrlString() throws Exception { + public void testGetContextUrl() throws Exception { request.setContextPath("foo/"); RequestContext context = new RequestContext(request, response, servletContext, model); assertEquals("foo/bar", context.getContextUrl("bar")); } @Test - public void testGetContextUrlStringMap() throws Exception { + public void testGetContextUrlWithMap() throws Exception { request.setContextPath("foo/"); RequestContext context = new RequestContext(request, response, servletContext, model); Map map = new HashMap(); @@ -66,7 +67,29 @@ public class RequestContextTests { map.put("spam", "bucket"); assertEquals("foo/bar?spam=bucket", context.getContextUrl("{foo}?spam={spam}", map)); } + + @Test + public void testGetContextUrlWithMapEscaping() throws Exception { + request.setContextPath("foo/"); + RequestContext context = new RequestContext(request, response, servletContext, model); + Map map = new HashMap(); + map.put("foo", "bar baz"); + map.put("spam", "&bucket="); + assertEquals("foo/bar%20baz?spam=%26bucket%3D", context.getContextUrl("{foo}?spam={spam}", map)); + } - // TODO: test escaping of query params (not supported by UriTemplate but some features present in UriUtils). + @Test + public void testPathToServlet() throws Exception { + request.setContextPath("/app"); + request.setServletPath("/servlet"); + RequestContext context = new RequestContext(request, response, servletContext, model); + + assertEquals("/app/servlet", context.getPathToServlet()); + + request.setAttribute(WebUtils.FORWARD_CONTEXT_PATH_ATTRIBUTE, "/origApp"); + request.setAttribute(WebUtils.FORWARD_SERVLET_PATH_ATTRIBUTE, "/origServlet"); + + assertEquals("/origApp/origServlet", context.getPathToServlet()); + } } diff --git a/org.springframework.web/src/main/java/org/springframework/web/util/UrlPathHelper.java b/org.springframework.web/src/main/java/org/springframework/web/util/UrlPathHelper.java index 707c8aff22..65a167bbe5 100644 --- a/org.springframework.web/src/main/java/org/springframework/web/util/UrlPathHelper.java +++ b/org.springframework.web/src/main/java/org/springframework/web/util/UrlPathHelper.java @@ -280,6 +280,20 @@ public class UrlPathHelper { return decodeRequestString(request, contextPath); } + /** + * Return the servlet path for the given request, detecting an include request + * URL if called within a RequestDispatcher include. + * @param request current HTTP request + * @return the servlet path + */ + public String getOriginatingServletPath(HttpServletRequest request) { + String servletPath = (String) request.getAttribute(WebUtils.FORWARD_SERVLET_PATH_ATTRIBUTE); + if (servletPath == null) { + servletPath = request.getServletPath(); + } + return servletPath; + } + /** * Return the query string part of the given request's URL. If this is a forwarded request, * correctly resolves to the query string of the original request.