diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java index d34f7168f98..a9834776c71 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilder.java @@ -832,6 +832,16 @@ public class MvcUriComponentsBuilder { return this; } + /** + * Use this method only if you need to apply strong encoding to expanded + * URI variables by quoting all characters with reserved meaning. + * @since 5.0.8 + */ + public MethodArgumentBuilder encode() { + this.baseUrl.encode(); + return this; + } + public String build() { return fromMethodInternal(this.baseUrl, this.controllerType, this.method, this.argumentValues) .build(false).encode().toUriString(); diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java index 61cbe330bd7..88140cc2c59 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/MvcUriComponentsBuilderTests.java @@ -363,12 +363,7 @@ public class MvcUriComponentsBuilderTests { @Test public void fromMappingNamePlain() { - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.setServletContext(new MockServletContext()); - context.register(WebConfig.class); - context.refresh(); - - this.request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); + initWebApplicationContext(WebConfig.class); this.request.setServerName("example.org"); this.request.setServerPort(9999); this.request.setContextPath("/base"); @@ -380,18 +375,35 @@ public class MvcUriComponentsBuilderTests { @Test public void fromMappingNameWithCustomBaseUrl() { - AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); - context.setServletContext(new MockServletContext()); - context.register(WebConfig.class); - context.refresh(); - - this.request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); + initWebApplicationContext(WebConfig.class); UriComponentsBuilder baseUrl = UriComponentsBuilder.fromUriString("http://example.org:9999/base"); MvcUriComponentsBuilder mvcBuilder = relativeTo(baseUrl); String url = mvcBuilder.withMappingName("PAC#getAddressesForCountry").arg(0, "DE").buildAndExpand(123); assertEquals("http://example.org:9999/base/people/123/addresses/DE", url); } + + @Test // SPR-17027 + public void fromMappingNameWithEncoding() { + initWebApplicationContext(WebConfig.class); + + this.request.setServerName("example.org"); + this.request.setServerPort(9999); + this.request.setContextPath("/base"); + + String mappingName = "PAC#getAddressesForCountry"; + String url = fromMappingName(mappingName).arg(0, "DE;FR").encode().buildAndExpand("_+_"); + assertEquals("/base/people/_%2B_/addresses/DE%3BFR", url); + } + + private void initWebApplicationContext(Class configClass) { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.setServletContext(new MockServletContext()); + context.register(configClass); + context.refresh(); + + this.request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); + } static class Person {