Polish ResponseBodyArgumentResolver

This commit is contained in:
Rossen Stoyanchev 2016-06-06 17:43:47 -04:00
parent 5c236e1edf
commit 0a88d5983a
2 changed files with 40 additions and 28 deletions

View File

@ -25,7 +25,6 @@ import reactor.core.publisher.Mono;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.converter.reactive.HttpMessageConverter; import org.springframework.http.converter.reactive.HttpMessageConverter;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
@ -35,8 +34,13 @@ import org.springframework.web.reactive.result.method.HandlerMethodArgumentResol
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
/** /**
* Resolves method arguments annotated with {@code @RequestBody} by reading and
* decoding the body of the request through a compatible
* {@code HttpMessageConverter}.
*
* @author Sebastien Deleuze * @author Sebastien Deleuze
* @author Stephane Maldini * @author Stephane Maldini
* @author Rossen Stoyanchev
*/ */
public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolver { public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolver {
@ -44,15 +48,30 @@ public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolve
private final ConversionService conversionService; private final ConversionService conversionService;
public RequestBodyArgumentResolver(List<HttpMessageConverter<?>> messageConverters,
/**
* Constructor with message converters and a ConversionService.
* @param converters converters for reading the request body with
* @param service for converting to other reactive types from Flux and Mono
*/
public RequestBodyArgumentResolver(List<HttpMessageConverter<?>> converters,
ConversionService service) { ConversionService service) {
Assert.notEmpty(messageConverters, "At least one message converter is required.");
Assert.notEmpty(converters, "At least one message converter is required.");
Assert.notNull(service, "'conversionService' is required."); Assert.notNull(service, "'conversionService' is required.");
this.messageConverters = messageConverters; this.messageConverters = converters;
this.conversionService = service; this.conversionService = service;
} }
/**
* Return the configured message converters.
*/
public List<HttpMessageConverter<?>> getMessageConverters() {
return this.messageConverters;
}
@Override @Override
public boolean supportsParameter(MethodParameter parameter) { public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestBody.class); return parameter.hasParameterAnnotation(RequestBody.class);
@ -70,35 +89,29 @@ public class RequestBodyArgumentResolver implements HandlerMethodArgumentResolve
mediaType = MediaType.APPLICATION_OCTET_STREAM; mediaType = MediaType.APPLICATION_OCTET_STREAM;
} }
Flux<DataBuffer> body = exchange.getRequest().getBody(); Flux<?> elementFlux = exchange.getRequest().getBody();
Flux<?> elementFlux;
HttpMessageConverter<?> messageConverter = HttpMessageConverter<?> converter = getMessageConverter(elementType, mediaType);
resolveMessageConverter(elementType, mediaType); if (converter != null) {
if (messageConverter != null) { elementFlux = converter.read(elementType, exchange.getRequest());
elementFlux = messageConverter.read(elementType, exchange.getRequest());
}
else {
elementFlux = body;
} }
if (this.conversionService.canConvert(Publisher.class, type.getRawClass())) { if (type.getRawClass() == Flux.class) {
return Mono.just(this.conversionService
.convert(elementFlux, type.getRawClass()));
}
else if (type.getRawClass() == Flux.class) {
return Mono.just(elementFlux); return Mono.just(elementFlux);
} }
else if (type.getRawClass() == Mono.class) { else if (type.getRawClass() == Mono.class) {
return Mono.just(Mono.from(elementFlux)); return Mono.just(Mono.from(elementFlux));
} }
else if (this.conversionService.canConvert(Publisher.class, type.getRawClass())) {
Object target = this.conversionService.convert(elementFlux, type.getRawClass());
return Mono.just(target);
}
// TODO Currently manage only "Foo" parameter, not "List<Foo>" parameters, Stéphane is going to add toIterable/toIterator to Flux to support that use case // TODO Currently manage only "Foo" parameter, not "List<Foo>" parameters, Stéphane is going to add toIterable/toIterator to Flux to support that use case
return elementFlux.next().map(o -> o); return elementFlux.next().map(o -> o);
} }
private HttpMessageConverter<?> resolveMessageConverter(ResolvableType type, private HttpMessageConverter<?> getMessageConverter(ResolvableType type, MediaType mediaType) {
MediaType mediaType) {
for (HttpMessageConverter<?> messageConverter : this.messageConverters) { for (HttpMessageConverter<?> messageConverter : this.messageConverters) {
if (messageConverter.canRead(type, mediaType)) { if (messageConverter.canRead(type, mediaType)) {
return messageConverter; return messageConverter;

View File

@ -78,14 +78,6 @@ public class ResponseBodyResultHandler extends ContentNegotiatingResultHandlerSu
this(converters, conversionService, new HeaderContentTypeResolver()); this(converters, conversionService, new HeaderContentTypeResolver());
} }
/**
* Return the configured message converters.
*/
public List<HttpMessageConverter<?>> getMessageConverters() {
return this.messageConverters;
}
/** /**
* Constructor with message converters, a {@code ConversionService}, and a * Constructor with message converters, a {@code ConversionService}, and a
* {@code RequestedContentTypeResolver}. * {@code RequestedContentTypeResolver}.
@ -105,6 +97,13 @@ public class ResponseBodyResultHandler extends ContentNegotiatingResultHandlerSu
} }
/**
* Return the configured message converters.
*/
public List<HttpMessageConverter<?>> getMessageConverters() {
return this.messageConverters;
}
@Override @Override
public boolean supports(HandlerResult result) { public boolean supports(HandlerResult result) {
Object handler = result.getHandler(); Object handler = result.getHandler();