parent
ce568468ae
commit
2a2fba6a37
|
@ -42,6 +42,7 @@ import org.springframework.lang.Nullable;
|
|||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
import org.springframework.web.service.annotation.HttpExchange;
|
||||
|
||||
/**
|
||||
|
@ -67,13 +68,13 @@ final class HttpServiceMethod {
|
|||
|
||||
HttpServiceMethod(
|
||||
Method method, Class<?> containingClass, List<HttpServiceArgumentResolver> argumentResolvers,
|
||||
HttpClientAdapter client, ReactiveAdapterRegistry reactiveRegistry,
|
||||
Duration blockTimeout) {
|
||||
HttpClientAdapter client, @Nullable StringValueResolver embeddedValueResolver,
|
||||
ReactiveAdapterRegistry reactiveRegistry, Duration blockTimeout) {
|
||||
|
||||
this.method = method;
|
||||
this.parameters = initMethodParameters(method);
|
||||
this.argumentResolvers = argumentResolvers;
|
||||
this.requestValuesInitializer = HttpRequestValuesInitializer.create(method, containingClass);
|
||||
this.requestValuesInitializer = HttpRequestValuesInitializer.create(method, containingClass, embeddedValueResolver);
|
||||
this.responseFunction = ResponseFunction.create(client, method, reactiveRegistry, blockTimeout);
|
||||
}
|
||||
|
||||
|
@ -161,7 +162,8 @@ final class HttpServiceMethod {
|
|||
/**
|
||||
* Introspect the method and create the request factory for it.
|
||||
*/
|
||||
public static HttpRequestValuesInitializer create(Method method, Class<?> containingClass) {
|
||||
public static HttpRequestValuesInitializer create(
|
||||
Method method, Class<?> containingClass, @Nullable StringValueResolver embeddedValueResolver) {
|
||||
|
||||
HttpExchange annot1 = AnnotatedElementUtils.findMergedAnnotation(containingClass, HttpExchange.class);
|
||||
HttpExchange annot2 = AnnotatedElementUtils.findMergedAnnotation(method, HttpExchange.class);
|
||||
|
@ -169,7 +171,7 @@ final class HttpServiceMethod {
|
|||
Assert.notNull(annot2, "Expected HttpRequest annotation");
|
||||
|
||||
HttpMethod httpMethod = initHttpMethod(annot1, annot2);
|
||||
String url = initUrl(annot1, annot2);
|
||||
String url = initUrl(annot1, annot2, embeddedValueResolver);
|
||||
MediaType contentType = initContentType(annot1, annot2);
|
||||
List<MediaType> acceptableMediaTypes = initAccept(annot1, annot2);
|
||||
|
||||
|
@ -194,11 +196,17 @@ final class HttpServiceMethod {
|
|||
}
|
||||
|
||||
@Nullable
|
||||
private static String initUrl(@Nullable HttpExchange typeAnnot, HttpExchange annot) {
|
||||
private static String initUrl(
|
||||
@Nullable HttpExchange typeAnnot, HttpExchange annot, @Nullable StringValueResolver embeddedValueResolver) {
|
||||
|
||||
String url1 = (typeAnnot != null ? typeAnnot.url() : null);
|
||||
String url2 = annot.url();
|
||||
|
||||
if (embeddedValueResolver != null) {
|
||||
url1 = (url1 != null ? embeddedValueResolver.resolveStringValue(url1) : null);
|
||||
url2 = embeddedValueResolver.resolveStringValue(url2);
|
||||
}
|
||||
|
||||
boolean hasUrl1 = StringUtils.hasText(url1);
|
||||
boolean hasUrl2 = StringUtils.hasText(url2);
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.springframework.core.convert.ConversionService;
|
|||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringValueResolver;
|
||||
import org.springframework.web.service.annotation.HttpExchange;
|
||||
|
||||
/**
|
||||
|
@ -50,6 +51,9 @@ public final class HttpServiceProxyFactory {
|
|||
|
||||
private final List<HttpServiceArgumentResolver> argumentResolvers;
|
||||
|
||||
@Nullable
|
||||
private final StringValueResolver embeddedValueResolver;
|
||||
|
||||
private final ReactiveAdapterRegistry reactiveAdapterRegistry;
|
||||
|
||||
private final Duration blockTimeout;
|
||||
|
@ -57,10 +61,12 @@ public final class HttpServiceProxyFactory {
|
|||
|
||||
private HttpServiceProxyFactory(
|
||||
HttpClientAdapter clientAdapter, List<HttpServiceArgumentResolver> argumentResolvers,
|
||||
ReactiveAdapterRegistry reactiveAdapterRegistry, Duration blockTimeout) {
|
||||
@Nullable StringValueResolver embeddedValueResolver, ReactiveAdapterRegistry reactiveAdapterRegistry,
|
||||
Duration blockTimeout) {
|
||||
|
||||
this.clientAdapter = clientAdapter;
|
||||
this.argumentResolvers = argumentResolvers;
|
||||
this.embeddedValueResolver = embeddedValueResolver;
|
||||
this.reactiveAdapterRegistry = reactiveAdapterRegistry;
|
||||
this.blockTimeout = blockTimeout;
|
||||
}
|
||||
|
@ -80,8 +86,8 @@ public final class HttpServiceProxyFactory {
|
|||
.stream()
|
||||
.map(method ->
|
||||
new HttpServiceMethod(
|
||||
method, serviceType, this.argumentResolvers,
|
||||
this.clientAdapter, this.reactiveAdapterRegistry, this.blockTimeout))
|
||||
method, serviceType, this.argumentResolvers, this.clientAdapter,
|
||||
this.embeddedValueResolver, this.reactiveAdapterRegistry, this.blockTimeout))
|
||||
.toList();
|
||||
|
||||
return ProxyFactory.getProxy(serviceType, new HttpServiceMethodInterceptor(methods));
|
||||
|
@ -114,6 +120,9 @@ public final class HttpServiceProxyFactory {
|
|||
@Nullable
|
||||
private ConversionService conversionService;
|
||||
|
||||
@Nullable
|
||||
private StringValueResolver embeddedValueResolver;
|
||||
|
||||
private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
|
||||
|
||||
private Duration blockTimeout = Duration.ofSeconds(5);
|
||||
|
@ -144,6 +153,18 @@ public final class HttpServiceProxyFactory {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the StringValueResolver to use for resolving placeholders and
|
||||
* expressions in {@link HttpExchange#url()}.
|
||||
* @param embeddedValueResolver the resolver to use
|
||||
* @return the same builder instance
|
||||
* @see org.springframework.context.EmbeddedValueResolverAware
|
||||
*/
|
||||
public Builder setEmbeddedValueResolver(@Nullable StringValueResolver embeddedValueResolver) {
|
||||
this.embeddedValueResolver = embeddedValueResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ReactiveAdapterRegistry} to use to support different
|
||||
* asynchronous types for HTTP service method return values.
|
||||
|
@ -176,7 +197,8 @@ public final class HttpServiceProxyFactory {
|
|||
List<HttpServiceArgumentResolver> resolvers = initArgumentResolvers(conversionService);
|
||||
|
||||
return new HttpServiceProxyFactory(
|
||||
this.clientAdapter, resolvers, this.reactiveAdapterRegistry, this.blockTimeout);
|
||||
this.clientAdapter, resolvers, this.embeddedValueResolver, this.reactiveAdapterRegistry,
|
||||
this.blockTimeout);
|
||||
}
|
||||
|
||||
private ConversionService initConversionService() {
|
||||
|
|
|
@ -168,7 +168,11 @@ public class HttpServiceMethodTests {
|
|||
@Test
|
||||
void typeAndMethodAnnotatedService() {
|
||||
|
||||
MethodLevelAnnotatedService service = this.proxyFactory.createClient(TypeAndMethodLevelAnnotatedService.class);
|
||||
HttpServiceProxyFactory proxyFactory = HttpServiceProxyFactory.builder(this.clientAdapter)
|
||||
.setEmbeddedValueResolver(value -> (value.equals("${baseUrl}") ? "/base" : value))
|
||||
.build();
|
||||
|
||||
MethodLevelAnnotatedService service = proxyFactory.createClient(TypeAndMethodLevelAnnotatedService.class);
|
||||
|
||||
service.performGet();
|
||||
|
||||
|
@ -281,7 +285,7 @@ public class HttpServiceMethodTests {
|
|||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@HttpExchange(url = "/base", contentType = APPLICATION_CBOR_VALUE, accept = APPLICATION_CBOR_VALUE)
|
||||
@HttpExchange(url = "${baseUrl}", contentType = APPLICATION_CBOR_VALUE, accept = APPLICATION_CBOR_VALUE)
|
||||
private interface TypeAndMethodLevelAnnotatedService extends MethodLevelAnnotatedService {
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue