Introduce ServerHttpMessageWriter/Reader to resolve hints

Issue: SPR-14693
This commit is contained in:
Sebastien Deleuze
2016-09-16 12:08:23 +02:00
parent 084daa7fb5
commit e74c59bf30
6 changed files with 307 additions and 12 deletions

View File

@@ -18,6 +18,7 @@ package org.springframework.web.reactive.result.method.annotation;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -32,6 +33,7 @@ import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.ServerHttpMessageReader;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
@@ -115,8 +117,8 @@ public abstract class AbstractMessageReaderArgumentResolver {
protected Mono<Object> readBody(MethodParameter bodyParameter, boolean isBodyRequired,
ServerWebExchange exchange) {
Class<?> bodyType = ResolvableType.forMethodParameter(bodyParameter).resolve();
ReactiveAdapter adapter = getAdapterRegistry().getAdapterTo(bodyType);
ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParameter);
ReactiveAdapter adapter = getAdapterRegistry().getAdapterTo(bodyType.resolve());
ResolvableType elementType = ResolvableType.forMethodParameter(bodyParameter);
if (adapter != null) {
@@ -130,9 +132,15 @@ public abstract class AbstractMessageReaderArgumentResolver {
}
for (HttpMessageReader<?> reader : getMessageReaders()) {
if (reader.canRead(elementType, mediaType, Collections.emptyMap())) {
Map<String, Object> hints = (reader instanceof ServerHttpMessageReader ?
((ServerHttpMessageReader<?>)reader).resolveReadHints(bodyType, elementType,
mediaType, exchange.getRequest()) : Collections.emptyMap());
if (reader.canRead(elementType, mediaType, hints)) {
if (adapter != null && adapter.getDescriptor().isMultiValue()) {
Flux<?> flux = reader.read(elementType, request, Collections.emptyMap())
Flux<?> flux = reader.read(elementType, request, hints)
.onErrorResumeWith(ex -> Flux.error(getReadError(ex, bodyParameter)));
if (checkRequired(adapter, isBodyRequired)) {
flux = flux.switchIfEmpty(Flux.error(getRequiredBodyError(bodyParameter)));
@@ -143,7 +151,7 @@ public abstract class AbstractMessageReaderArgumentResolver {
return Mono.just(adapter.fromPublisher(flux));
}
else {
Mono<?> mono = reader.readMono(elementType, request, Collections.emptyMap())
Mono<?> mono = reader.readMono(elementType, request, hints)
.otherwise(ex -> Mono.error(getReadError(ex, bodyParameter)));
if (checkRequired(adapter, isBodyRequired)) {
mono = mono.otherwiseIfEmpty(Mono.error(getRequiredBodyError(bodyParameter)));

View File

@@ -17,6 +17,7 @@ package org.springframework.web.reactive.result.method.annotation;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.reactivestreams.Publisher;
@@ -28,6 +29,7 @@ import org.springframework.core.ReactiveAdapterRegistry;
import org.springframework.core.ResolvableType;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.ServerHttpMessageWriter;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.Assert;
import org.springframework.web.reactive.accept.RequestedContentTypeResolver;
@@ -89,10 +91,10 @@ public abstract class AbstractMessageWriterResultHandler extends ContentNegotiat
@SuppressWarnings("unchecked")
protected Mono<Void> writeBody(Object body, MethodParameter bodyType, ServerWebExchange exchange) {
protected Mono<Void> writeBody(Object body, MethodParameter bodyParameter, ServerWebExchange exchange) {
Class<?> bodyClass = bodyType.getParameterType();
ReactiveAdapter adapter = getAdapterRegistry().getAdapterFrom(bodyClass, body);
ResolvableType bodyType = ResolvableType.forMethodParameter(bodyParameter);
ReactiveAdapter adapter = getAdapterRegistry().getAdapterFrom(bodyType.resolve(), body);
Publisher<?> publisher;
ResolvableType elementType;
@@ -100,11 +102,11 @@ public abstract class AbstractMessageWriterResultHandler extends ContentNegotiat
publisher = adapter.toPublisher(body);
elementType = adapter.getDescriptor().isNoValue() ?
ResolvableType.forClass(Void.class) :
ResolvableType.forMethodParameter(bodyType).getGeneric(0);
bodyType.getGeneric(0);
}
else {
publisher = Mono.justOrEmpty(body);
elementType = ResolvableType.forMethodParameter(bodyType);
elementType = bodyType;
}
if (void.class == elementType.getRawClass() || Void.class == elementType.getRawClass()) {
@@ -121,10 +123,14 @@ public abstract class AbstractMessageWriterResultHandler extends ContentNegotiat
if (bestMediaType != null) {
for (HttpMessageWriter<?> messageWriter : getMessageWriters()) {
if (messageWriter.canWrite(elementType, bestMediaType, Collections.emptyMap())) {
Map<String, Object> hints = (messageWriter instanceof ServerHttpMessageWriter ?
((ServerHttpMessageWriter<?>)messageWriter).resolveWriteHints(bodyType, elementType,
bestMediaType, exchange.getRequest()) : Collections.emptyMap());
if (messageWriter.canWrite(elementType, bestMediaType, hints)) {
ServerHttpResponse response = exchange.getResponse();
return messageWriter.write((Publisher) publisher, elementType,
bestMediaType, response, Collections.emptyMap());
bestMediaType, response, hints);
}
}
}