diff --git a/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java b/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java index 5452caf3ea2..3fc5d1916f5 100644 --- a/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java +++ b/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java @@ -152,8 +152,9 @@ public class AsyncRestTemplate extends InterceptingAsyncHttpAccessor implements } /** - * Set a custom {@link UriTemplateHandler} for expanding URI templates. - *

By default, RestTemplate uses {@link DefaultUriTemplateHandler}. + * This property has the same purpose as the corresponding property on the + * {@code RestTemplate}. For more details see + * {@link RestTemplate#setUriTemplateHandler}. * @param handler the URI template handler to use */ public void setUriTemplateHandler(UriTemplateHandler handler) { diff --git a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java index 85b1d985cd8..7a841b6fbfd 100644 --- a/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java +++ b/spring-web/src/main/java/org/springframework/web/client/RestTemplate.java @@ -237,8 +237,12 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat } /** - * Set a custom {@link UriTemplateHandler} for expanding URI templates. - *

By default, RestTemplate uses {@link DefaultUriTemplateHandler}. + * Configure the {@link UriTemplateHandler} to use to expand URI templates. + * By default the {@link DefaultUriTemplateHandler} is used which relies on + * Spring's URI template support and exposes several useful properties that + * customize its behavior for encoding and for prepending a common base URL. + * An alternative implementation may be used to plug an external URI + * template library. * @param handler the URI template handler to use */ public void setUriTemplateHandler(UriTemplateHandler handler) { diff --git a/spring-web/src/main/java/org/springframework/web/util/DefaultUriTemplateHandler.java b/spring-web/src/main/java/org/springframework/web/util/DefaultUriTemplateHandler.java index 0eb9acf8f41..00d62a624ad 100644 --- a/spring-web/src/main/java/org/springframework/web/util/DefaultUriTemplateHandler.java +++ b/spring-web/src/main/java/org/springframework/web/util/DefaultUriTemplateHandler.java @@ -24,8 +24,8 @@ import java.util.Map; import org.springframework.util.Assert; /** - * Default implementation of {@link UriTemplateHandler} that relies on - * {@link UriComponentsBuilder} internally. + * Default implementation of {@link UriTemplateHandler} that uses + * {@link UriComponentsBuilder} to expand and encode variables. * * @author Rossen Stoyanchev * @since 4.2 @@ -38,14 +38,10 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler { /** - * Configure a base URL to prepend URI templates with. The base URL should - * have a scheme and host but may also contain a port and a partial path. - * Individual URI templates then may provide the remaining part of the URL - * including additional path, query and fragment. - *

Note: Individual URI templates are expanded and - * encoded before being appended to the base URL. Therefore the base URL is - * expected to be fully expanded and encoded, which can be done with the help - * of {@link UriComponentsBuilder}. + * Configure a base URL to prepend URI templates with. The base URL must + * have a scheme and host but may optionally contain a port and a path. + * The base URL must be fully expanded and encoded which can be done via + * {@link UriComponentsBuilder}. * @param baseUrl the base URL. */ public void setBaseUrl(String baseUrl) { @@ -68,10 +64,10 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler { /** * Whether to parse the path of a URI template string into path segments. - *

If set to {@code true} the path of parsed URI templates is decomposed - * into path segments so that URI variables expanded into the path are - * treated according to path segment encoding rules. In effect that means the - * "/" character is percent encoded. + *

If set to {@code true} the URI template path is immediately decomposed + * into path segments any URI variables expanded into it are then subject to + * path segment encoding rules. In effect URI variables in the path have any + * "/" characters percent encoded. *

By default this is set to {@code false} in which case the path is kept * as a full path and expanded URI variables will preserve "/" characters. * @param parsePath whether to parse the path into path segments @@ -102,6 +98,11 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler { return insertBaseUrl(url); } + /** + * Create a {@code UriComponentsBuilder} from the UriTemplate string. The + * default implementation also parses the path into path segments if + * {@link #setParsePath parsePath} is enabled. + */ protected UriComponentsBuilder initUriComponentsBuilder(String uriTemplate) { UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(uriTemplate); if (shouldParsePath()) { @@ -114,6 +115,12 @@ public class DefaultUriTemplateHandler implements UriTemplateHandler { return builder; } + /** + * Invoked after the URI template has been expanded and encoded to prepend + * the configured {@link #setBaseUrl(String) baseUrl} if any. + * @param uriComponents the expanded and encoded URI + * @return the final URI + */ protected URI insertBaseUrl(UriComponents uriComponents) { if (getBaseUrl() == null || uriComponents.getHost() != null) { return uriComponents.toUri(); diff --git a/spring-web/src/main/java/org/springframework/web/util/UriTemplateHandler.java b/spring-web/src/main/java/org/springframework/web/util/UriTemplateHandler.java index ac04e31e10a..c03eb191ab4 100644 --- a/spring-web/src/main/java/org/springframework/web/util/UriTemplateHandler.java +++ b/spring-web/src/main/java/org/springframework/web/util/UriTemplateHandler.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -20,15 +20,23 @@ import java.net.URI; import java.util.Map; /** - * A strategy for expanding a URI template with URI variables into a {@link URI}. + * Strategy for expanding a URI template with full control over the URI template + * syntax and the encoding of variables. Also a convenient central point for + * pre-processing all URI templates for example to insert a common base path. + * + *

Supported as a property on the {@code RestTemplate} as well as the + * {@code AsyncRestTemplate}. The {@link DefaultUriTemplateHandler} is built + * on Spring's URI template support via {@link UriComponentsBuilder}. An + * alternative implementation may be used to plug external URI template libraries. * * @author Rossen Stoyanchev * @since 4.2 + * @see org.springframework.web.client.RestTemplate#setUriTemplateHandler */ public interface UriTemplateHandler { /** - * Expand the give URI template with a map of URI variables. + * Expand the given URI template from a map of URI variables. * @param uriTemplate the URI template string * @param uriVariables the URI variables * @return the resulting URI @@ -36,11 +44,11 @@ public interface UriTemplateHandler { URI expand(String uriTemplate, Map uriVariables); /** - * Expand the give URI template with an array of URI variable values. + * Expand the given URI template from an array of URI variables. * @param uriTemplate the URI template string - * @param uriVariableValues the URI variable values + * @param uriVariables the URI variable values * @return the resulting URI */ - URI expand(String uriTemplate, Object... uriVariableValues); + URI expand(String uriTemplate, Object... uriVariables); } diff --git a/spring-web/src/test/java/org/springframework/web/util/DefaultUriTemplateHandlerTests.java b/spring-web/src/test/java/org/springframework/web/util/DefaultUriTemplateHandlerTests.java index 1642351edc0..dd6c67c3d50 100644 --- a/spring-web/src/test/java/org/springframework/web/util/DefaultUriTemplateHandlerTests.java +++ b/spring-web/src/test/java/org/springframework/web/util/DefaultUriTemplateHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -15,35 +15,27 @@ */ package org.springframework.web.util; -import static org.junit.Assert.assertEquals; - import java.net.URI; import java.util.HashMap; import java.util.Map; -import org.junit.Before; import org.junit.Test; +import static org.junit.Assert.assertEquals; + /** * Unit tests for {@link DefaultUriTemplateHandler}. * @author Rossen Stoyanchev */ public class DefaultUriTemplateHandlerTests { - private DefaultUriTemplateHandler handler; - - - @Before - public void setUp() throws Exception { - this.handler = new DefaultUriTemplateHandler(); - } + private final DefaultUriTemplateHandler handler = new DefaultUriTemplateHandler(); @Test public void baseUrl() throws Exception { this.handler.setBaseUrl("http://localhost:8080"); URI actual = this.handler.expand("/myapiresource"); - URI expected = new URI("http://localhost:8080/myapiresource"); assertEquals(expected, actual); } @@ -52,35 +44,30 @@ public class DefaultUriTemplateHandlerTests { public void baseUrlWithPartialPath() throws Exception { this.handler.setBaseUrl("http://localhost:8080/context"); URI actual = this.handler.expand("/myapiresource"); - URI expected = new URI("http://localhost:8080/context/myapiresource"); assertEquals(expected, actual); } @Test public void expandWithFullPath() throws Exception { - Map vars = new HashMap(2); + Map vars = new HashMap<>(2); vars.put("hotel", "1"); vars.put("publicpath", "pics/logo.png"); String template = "http://example.com/hotels/{hotel}/pic/{publicpath}"; - URI actual = this.handler.expand(template, vars); - URI expected = new URI("http://example.com/hotels/1/pic/pics/logo.png"); assertEquals(expected, actual); } @Test public void expandWithFullPathAndParsePathEnabled() throws Exception { - Map vars = new HashMap(2); + this.handler.setParsePath(true); + Map vars = new HashMap<>(2); vars.put("hotel", "1"); vars.put("publicpath", "pics/logo.png"); vars.put("scale", "150x150"); String template = "http://example.com/hotels/{hotel}/pic/{publicpath}/size/{scale}"; - - this.handler.setParsePath(true); URI actual = this.handler.expand(template, vars); - URI expected = new URI("http://example.com/hotels/1/pic/pics%2Flogo.png/size/150x150"); assertEquals(expected, actual); }