Add baseUrl overloaded MvcUriComponentsBuilder methods
Issue: SPR-12800
This commit is contained in:
parent
7f9975e34d
commit
febcd0c46d
|
@ -697,7 +697,7 @@ public class UriComponentsBuilder implements Cloneable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object clone() {
|
public Object clone() {
|
||||||
return new UriComponentsBuilder(this);
|
return new UriComponentsBuilder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.aopalliance.intercept.MethodInterceptor;
|
import org.aopalliance.intercept.MethodInterceptor;
|
||||||
|
@ -122,8 +123,28 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
|
||||||
* @return a UriComponentsBuilder instance (never {@code null})
|
* @return a UriComponentsBuilder instance (never {@code null})
|
||||||
*/
|
*/
|
||||||
public static UriComponentsBuilder fromController(Class<?> controllerType) {
|
public static UriComponentsBuilder fromController(Class<?> controllerType) {
|
||||||
|
return fromController(null, controllerType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An alternative to {@link #fromController(Class)} that accepts a
|
||||||
|
* {@code UriComponentsBuilder} representing the base URL. This is useful
|
||||||
|
* when using MvcUriComponentsBuilder outside the context of processing a
|
||||||
|
* request or to apply a custom baseUrl not matching the current request.
|
||||||
|
* @param builder the builder for the base URL; the builder will be cloned
|
||||||
|
* and therefore not modified and may be re-used for further calls.
|
||||||
|
* @param controllerType the controller to build a URI for
|
||||||
|
* @return a UriComponentsBuilder instance (never {@code null})
|
||||||
|
*/
|
||||||
|
public static UriComponentsBuilder fromController(UriComponentsBuilder builder, Class<?> controllerType) {
|
||||||
|
if (builder != null) {
|
||||||
|
builder = (UriComponentsBuilder) builder.clone();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder = ServletUriComponentsBuilder.fromCurrentServletMapping();
|
||||||
|
}
|
||||||
String mapping = getTypeRequestMapping(controllerType);
|
String mapping = getTypeRequestMapping(controllerType);
|
||||||
return ServletUriComponentsBuilder.fromCurrentServletMapping().path(mapping);
|
return builder.path(mapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getTypeRequestMapping(Class<?> controllerType) {
|
private static String getTypeRequestMapping(Class<?> controllerType) {
|
||||||
|
@ -144,29 +165,49 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
|
||||||
* to {@link #fromMethod(java.lang.reflect.Method, Object...)}.
|
* to {@link #fromMethod(java.lang.reflect.Method, Object...)}.
|
||||||
* @param controllerType the controller
|
* @param controllerType the controller
|
||||||
* @param methodName the method name
|
* @param methodName the method name
|
||||||
* @param argumentValues the argument values
|
* @param args the argument values
|
||||||
* @return a UriComponentsBuilder instance, never {@code null}
|
* @return a UriComponentsBuilder instance, never {@code null}
|
||||||
* @throws IllegalArgumentException if there is no matching or
|
* @throws IllegalArgumentException if there is no matching or
|
||||||
* if there is more than one matching method
|
* if there is more than one matching method
|
||||||
*/
|
*/
|
||||||
public static UriComponentsBuilder fromMethodName(Class<?> controllerType, String methodName, Object... argumentValues) {
|
public static UriComponentsBuilder fromMethodName(Class<?> controllerType, String methodName, Object... args) {
|
||||||
Method method = getMethod(controllerType, methodName, argumentValues);
|
return fromMethodName(null, controllerType, methodName, args);
|
||||||
return fromMethod(method, argumentValues);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Method getMethod(Class<?> controllerType, String methodName, Object... argumentValues) {
|
/**
|
||||||
|
* An alternative to {@link #fromMethodName(Class, String, Object...)} that
|
||||||
|
* accepts a {@code UriComponentsBuilder} representing the base URL. This is
|
||||||
|
* useful when using MvcUriComponentsBuilder outside the context of processing
|
||||||
|
* a request or to apply a custom baseUrl not matching the current request.
|
||||||
|
* @param builder the builder for the base URL; the builder will be cloned
|
||||||
|
* and therefore not modified and may be re-used for further calls.
|
||||||
|
* @param controllerType the controller
|
||||||
|
* @param methodName the method name
|
||||||
|
* @param args the argument values
|
||||||
|
* @return a UriComponentsBuilder instance, never {@code null}
|
||||||
|
* @throws IllegalArgumentException if there is no matching or
|
||||||
|
* if there is more than one matching method
|
||||||
|
*/
|
||||||
|
public static UriComponentsBuilder fromMethodName(UriComponentsBuilder builder,
|
||||||
|
Class<?> controllerType, String methodName, Object... args) {
|
||||||
|
|
||||||
|
Method method = getMethod(controllerType, methodName, args);
|
||||||
|
return fromMethod(builder, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Method getMethod(Class<?> controllerType, String methodName, Object... args) {
|
||||||
Method match = null;
|
Method match = null;
|
||||||
for (Method method : controllerType.getDeclaredMethods()) {
|
for (Method method : controllerType.getDeclaredMethods()) {
|
||||||
if (method.getName().equals(methodName) && method.getParameterTypes().length == argumentValues.length) {
|
if (method.getName().equals(methodName) && method.getParameterTypes().length == args.length) {
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
throw new IllegalArgumentException("Found two methods named '" + methodName + "' having " +
|
throw new IllegalArgumentException("Found two methods named '" + methodName + "' having " +
|
||||||
Arrays.asList(argumentValues) + " arguments, controller " + controllerType.getName());
|
Arrays.asList(args) + " arguments, controller " + controllerType.getName());
|
||||||
}
|
}
|
||||||
match = method;
|
match = method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (match == null) {
|
if (match == null) {
|
||||||
throw new IllegalArgumentException("No method '" + methodName + "' with " + argumentValues.length +
|
throw new IllegalArgumentException("No method '" + methodName + "' with " + args.length +
|
||||||
" parameters found in " + controllerType.getName());
|
" parameters found in " + controllerType.getName());
|
||||||
}
|
}
|
||||||
return match;
|
return match;
|
||||||
|
@ -208,9 +249,24 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
|
||||||
* @return a UriComponents instance
|
* @return a UriComponents instance
|
||||||
*/
|
*/
|
||||||
public static UriComponentsBuilder fromMethodCall(Object invocationInfo) {
|
public static UriComponentsBuilder fromMethodCall(Object invocationInfo) {
|
||||||
|
return fromMethodCall(null, invocationInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An alternative to {@link #fromMethodCall(Object)} that accepts a
|
||||||
|
* {@code UriComponentsBuilder} representing the base URL. This is useful
|
||||||
|
* when using MvcUriComponentsBuilder outside the context of processing a
|
||||||
|
* request or to apply a custom baseUrl not matching the current request.
|
||||||
|
* @param builder the builder for the base URL; the builder will be cloned
|
||||||
|
* and therefore not modified and may be re-used for further calls.
|
||||||
|
* @param invocationInfo either the value returned from a "mock" controller
|
||||||
|
* invocation or the "mock" controller itself after an invocation
|
||||||
|
* @return a UriComponents instance
|
||||||
|
*/
|
||||||
|
public static UriComponentsBuilder fromMethodCall(UriComponentsBuilder builder, Object invocationInfo) {
|
||||||
Assert.isInstanceOf(MethodInvocationInfo.class, invocationInfo);
|
Assert.isInstanceOf(MethodInvocationInfo.class, invocationInfo);
|
||||||
MethodInvocationInfo info = (MethodInvocationInfo) invocationInfo;
|
MethodInvocationInfo info = (MethodInvocationInfo) invocationInfo;
|
||||||
return fromMethod(info.getControllerMethod(), info.getArgumentValues());
|
return fromMethod(builder, info.getControllerMethod(), info.getArgumentValues());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -277,20 +333,42 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
|
||||||
* and an array of method argument values. The array of values must match the
|
* and an array of method argument values. The array of values must match the
|
||||||
* signature of the controller method. Values for {@code @RequestParam} and
|
* signature of the controller method. Values for {@code @RequestParam} and
|
||||||
* {@code @PathVariable} are used for building the URI (via implementations of
|
* {@code @PathVariable} are used for building the URI (via implementations of
|
||||||
* {@link org.springframework.web.method.support.UriComponentsContributor})
|
* {@link org.springframework.web.method.support.UriComponentsContributor
|
||||||
* while remaining argument values are ignored and can be {@code null}.
|
* UriComponentsContributor}) while remaining argument values are ignored and
|
||||||
|
* can be {@code null}.
|
||||||
* @param method the controller method
|
* @param method the controller method
|
||||||
* @param argumentValues argument values for the controller method
|
* @param args argument values for the controller method
|
||||||
* @return a UriComponentsBuilder instance, never {@code null}
|
* @return a UriComponentsBuilder instance, never {@code null}
|
||||||
*/
|
*/
|
||||||
public static UriComponentsBuilder fromMethod(Method method, Object... argumentValues) {
|
public static UriComponentsBuilder fromMethod(Method method, Object... args) {
|
||||||
|
return fromMethod(null, method, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An alternative to {@link #fromMethod(java.lang.reflect.Method, Object...)}
|
||||||
|
* that accepts a {@code UriComponentsBuilder} representing the base URL.
|
||||||
|
* This is useful when using MvcUriComponentsBuilder outside the context of
|
||||||
|
* processing a request or to apply a custom baseUrl not matching the
|
||||||
|
* current request.
|
||||||
|
* @param builder the builder for the base URL; the builder will be cloned
|
||||||
|
* and therefore not modified and may be re-used for further calls.
|
||||||
|
* @param method the controller method
|
||||||
|
* @param args argument values for the controller method
|
||||||
|
* @return a UriComponentsBuilder instance, never {@code null}
|
||||||
|
*/
|
||||||
|
public static UriComponentsBuilder fromMethod(UriComponentsBuilder builder, Method method, Object... args) {
|
||||||
|
if (builder != null) {
|
||||||
|
builder = (UriComponentsBuilder) builder.clone();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
builder = ServletUriComponentsBuilder.fromCurrentServletMapping();
|
||||||
|
}
|
||||||
String typePath = getTypeRequestMapping(method.getDeclaringClass());
|
String typePath = getTypeRequestMapping(method.getDeclaringClass());
|
||||||
String methodPath = getMethodRequestMapping(method);
|
String methodPath = getMethodRequestMapping(method);
|
||||||
String path = pathMatcher.combine(typePath, methodPath);
|
String path = pathMatcher.combine(typePath, methodPath);
|
||||||
|
builder.path(path);
|
||||||
UriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentServletMapping().path(path);
|
UriComponents uriComponents = applyContributors(builder, method, args);
|
||||||
UriComponents uriComponents = applyContributors(builder, method, argumentValues);
|
return UriComponentsBuilder.newInstance().uriComponents(uriComponents);
|
||||||
return ServletUriComponentsBuilder.newInstance().uriComponents(uriComponents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getMethodRequestMapping(Method method) {
|
private static String getMethodRequestMapping(Method method) {
|
||||||
|
@ -453,7 +531,7 @@ public class MvcUriComponentsBuilder extends UriComponentsBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object clone() {
|
public Object clone() {
|
||||||
return new MvcUriComponentsBuilder(this);
|
return new MvcUriComponentsBuilder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -223,7 +223,7 @@ public class ServletUriComponentsBuilder extends UriComponentsBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object clone() {
|
public Object clone() {
|
||||||
return new ServletUriComponentsBuilder(this);
|
return new ServletUriComponentsBuilder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2012-2014 the original author or authors.
|
* Copyright 2012-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
package org.springframework.web.servlet.mvc.method.annotation;
|
package org.springframework.web.servlet.mvc.method.annotation;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.*;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -38,10 +42,7 @@ import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
import org.springframework.web.util.UriComponents;
|
import org.springframework.web.util.UriComponents;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
import static org.hamcrest.Matchers.*;
|
|
||||||
import static org.junit.Assert.*;
|
|
||||||
import static org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder}.
|
* Unit tests for {@link org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder}.
|
||||||
|
@ -98,6 +99,15 @@ public class MvcUriComponentsBuilderTests {
|
||||||
assertThat(uriComponents.toUriString(), is("http://localhost/"));
|
assertThat(uriComponents.toUriString(), is("http://localhost/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromControllerWithCustomBaseUrl() {
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
|
||||||
|
UriComponents uriComponents = fromController(builder, PersonControllerImpl.class).build();
|
||||||
|
|
||||||
|
assertEquals("http://example.org:9090/base/people", uriComponents.toString());
|
||||||
|
assertEquals("http://example.org:9090/base", builder.toUriString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromMethodNamePathVariable() throws Exception {
|
public void testFromMethodNamePathVariable() throws Exception {
|
||||||
UriComponents uriComponents = fromMethodName(
|
UriComponents uriComponents = fromMethodName(
|
||||||
|
@ -151,6 +161,16 @@ public class MvcUriComponentsBuilderTests {
|
||||||
assertThat(uriComponents.toUriString(), is("http://localhost/"));
|
assertThat(uriComponents.toUriString(), is("http://localhost/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromMethodNameWithCustomBaseUrl() throws Exception {
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
|
||||||
|
UriComponents uriComponents = fromMethodName(builder, ControllerWithMethods.class,
|
||||||
|
"methodWithPathVariable", new Object[] {"1"}).build();
|
||||||
|
|
||||||
|
assertEquals("http://example.org:9090/base/something/1/foo", uriComponents.toString());
|
||||||
|
assertEquals("http://example.org:9090/base", builder.toUriString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFromMethodCall() {
|
public void testFromMethodCall() {
|
||||||
UriComponents uriComponents = fromMethodCall(on(ControllerWithMethods.class).myMethod(null)).build();
|
UriComponents uriComponents = fromMethodCall(on(ControllerWithMethods.class).myMethod(null)).build();
|
||||||
|
@ -201,6 +221,15 @@ public class MvcUriComponentsBuilderTests {
|
||||||
assertThat(queryParams.get("items"), containsInAnyOrder("3", "7"));
|
assertThat(queryParams.get("items"), containsInAnyOrder("3", "7"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFromMethodCallWithCustomBaseUrl() {
|
||||||
|
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("http://example.org:9090/base");
|
||||||
|
UriComponents uriComponents = fromMethodCall(builder, on(ControllerWithMethods.class).myMethod(null)).build();
|
||||||
|
|
||||||
|
assertEquals("http://example.org:9090/base/something/else", uriComponents.toString());
|
||||||
|
assertEquals("http://example.org:9090/base", builder.toUriString());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void usesForwardedHostAsHostIfHeaderIsSet() {
|
public void usesForwardedHostAsHostIfHeaderIsSet() {
|
||||||
this.request.addHeader("X-Forwarded-Host", "somethingDifferent");
|
this.request.addHeader("X-Forwarded-Host", "somethingDifferent");
|
||||||
|
|
Loading…
Reference in New Issue