提交 ad91b942 编写于 作者: R Rossen Stoyanchev

Require Encoder & Decoder in Reader & Writer wrappers

When CodecHttpMessageConverter was split into DecoderHttpMessageReader
and EncoderHttpMessageWriter the null checks were never removed.

This commit makes the Encoder and Decoder instances provided to their
respective wrappers required.
上级 1940f8cf
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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.
...@@ -25,12 +25,13 @@ import reactor.core.publisher.Mono; ...@@ -25,12 +25,13 @@ import reactor.core.publisher.Mono;
import org.springframework.core.ResolvableType; import org.springframework.core.ResolvableType;
import org.springframework.core.codec.Decoder; import org.springframework.core.codec.Decoder;
import org.springframework.http.HttpMessage;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ReactiveHttpInputMessage; import org.springframework.http.ReactiveHttpInputMessage;
import org.springframework.util.Assert;
/** /**
* Implementation of the {@link HttpMessageReader} interface that delegates * Implementation of {@code HttpMessageReader} delegating to a {@link Decoder}.
* to a {@link Decoder}.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Sebastien Deleuze * @author Sebastien Deleuze
...@@ -41,50 +42,54 @@ public class DecoderHttpMessageReader<T> implements HttpMessageReader<T> { ...@@ -41,50 +42,54 @@ public class DecoderHttpMessageReader<T> implements HttpMessageReader<T> {
private final Decoder<T> decoder; private final Decoder<T> decoder;
private final List<MediaType> readableMediaTypes; private final List<MediaType> mediaTypes;
/** /**
* Create a {@code CodecHttpMessageConverter} with the given {@link Decoder}. * Create an instance wrapping the given {@link Decoder}.
* @param decoder the decoder to use
*/ */
public DecoderHttpMessageReader(Decoder<T> decoder) { public DecoderHttpMessageReader(Decoder<T> decoder) {
Assert.notNull(decoder, "Decoder is required");
this.decoder = decoder; this.decoder = decoder;
this.readableMediaTypes = (decoder != null ? this.mediaTypes = MediaType.asMediaTypes(decoder.getDecodableMimeTypes());
MediaType.asMediaTypes(decoder.getDecodableMimeTypes()) : Collections.emptyList());
} }
@Override /**
public boolean canRead(ResolvableType elementType, MediaType mediaType) { * Return the {@link Decoder} of this reader.
return this.decoder != null && this.decoder.canDecode(elementType, mediaType); */
public Decoder<T> getDecoder() {
return this.decoder;
} }
@Override @Override
public List<MediaType> getReadableMediaTypes() { public List<MediaType> getReadableMediaTypes() {
return this.readableMediaTypes; return this.mediaTypes;
} }
@Override @Override
public Flux<T> read(ResolvableType elementType, ReactiveHttpInputMessage inputMessage, Map<String, Object> hints) { public boolean canRead(ResolvableType elementType, MediaType mediaType) {
if (this.decoder == null) { return this.decoder.canDecode(elementType, mediaType);
return Flux.error(new IllegalStateException("No decoder set")); }
}
@Override
public Flux<T> read(ResolvableType elementType, ReactiveHttpInputMessage inputMessage,
Map<String, Object> hints) {
MediaType contentType = getContentType(inputMessage); MediaType contentType = getContentType(inputMessage);
return this.decoder.decode(inputMessage.getBody(), elementType, contentType, hints); return this.decoder.decode(inputMessage.getBody(), elementType, contentType, hints);
} }
@Override @Override
public Mono<T> readMono(ResolvableType elementType, ReactiveHttpInputMessage inputMessage, Map<String, Object> hints) { public Mono<T> readMono(ResolvableType elementType, ReactiveHttpInputMessage inputMessage,
if (this.decoder == null) { Map<String, Object> hints) {
return Mono.error(new IllegalStateException("No decoder set"));
}
MediaType contentType = getContentType(inputMessage); MediaType contentType = getContentType(inputMessage);
return this.decoder.decodeToMono(inputMessage.getBody(), elementType, contentType, hints); return this.decoder.decodeToMono(inputMessage.getBody(), elementType, contentType, hints);
} }
private MediaType getContentType(ReactiveHttpInputMessage inputMessage) { private MediaType getContentType(HttpMessage inputMessage) {
MediaType contentType = inputMessage.getHeaders().getContentType(); MediaType contentType = inputMessage.getHeaders().getContentType();
return (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM); return (contentType != null ? contentType : MediaType.APPLICATION_OCTET_STREAM);
} }
......
/* /*
* Copyright 2002-2016 the original author or authors. * Copyright 2002-2017 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,13 +16,10 @@ ...@@ -16,13 +16,10 @@
package org.springframework.http.codec; package org.springframework.http.codec;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.reactivestreams.Publisher; import org.reactivestreams.Publisher;
import static org.springframework.core.codec.AbstractEncoder.FLUSHING_STRATEGY_HINT;
import static org.springframework.core.codec.AbstractEncoder.FlushingStrategy.AFTER_EACH_ELEMENT;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
...@@ -33,10 +30,13 @@ import org.springframework.core.io.buffer.DataBufferFactory; ...@@ -33,10 +30,13 @@ import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ReactiveHttpOutputMessage; import org.springframework.http.ReactiveHttpOutputMessage;
import org.springframework.util.Assert;
import static org.springframework.core.codec.AbstractEncoder.FLUSHING_STRATEGY_HINT;
import static org.springframework.core.codec.AbstractEncoder.FlushingStrategy.AFTER_EACH_ELEMENT;
/** /**
* Implementation of the {@link HttpMessageWriter} interface that delegates * Implementation of {@code HttpMessageWriter} delegating to an {@link Encoder}.
* to an {@link Encoder}.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Sebastien Deleuze * @author Sebastien Deleuze
...@@ -47,40 +47,42 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> { ...@@ -47,40 +47,42 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
private final Encoder<T> encoder; private final Encoder<T> encoder;
private final List<MediaType> writableMediaTypes; private final List<MediaType> mediaTypes;
/** /**
* Create a {@code CodecHttpMessageConverter} with the given {@link Encoder}. * Create an instance wrapping the given {@link Encoder}.
* @param encoder the encoder to use
*/ */
public EncoderHttpMessageWriter(Encoder<T> encoder) { public EncoderHttpMessageWriter(Encoder<T> encoder) {
Assert.notNull(encoder, "Encoder is required");
this.encoder = encoder; this.encoder = encoder;
this.writableMediaTypes = (encoder != null ? this.mediaTypes = MediaType.asMediaTypes(encoder.getEncodableMimeTypes());
MediaType.asMediaTypes(encoder.getEncodableMimeTypes()) : Collections.emptyList());
} }
@Override /**
public boolean canWrite(ResolvableType elementType, MediaType mediaType) { * Return the {@code Encoder} of this writer.
return this.encoder != null && this.encoder.canEncode(elementType, mediaType); */
public Encoder<T> getEncoder() {
return this.encoder;
} }
@Override @Override
public List<MediaType> getWritableMediaTypes() { public List<MediaType> getWritableMediaTypes() {
return this.writableMediaTypes; return this.mediaTypes;
} }
@Override
public boolean canWrite(ResolvableType elementType, MediaType mediaType) {
return this.encoder.canEncode(elementType, mediaType);
}
@Override @Override
public Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType elementType, public Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType elementType,
MediaType mediaType, ReactiveHttpOutputMessage outputMessage, MediaType mediaType, ReactiveHttpOutputMessage outputMessage,
Map<String, Object> hints) { Map<String, Object> hints) {
if (this.encoder == null) {
return Mono.error(new IllegalStateException("No decoder set"));
}
HttpHeaders headers = outputMessage.getHeaders(); HttpHeaders headers = outputMessage.getHeaders();
if (headers.getContentType() == null) { if (headers.getContentType() == null) {
MediaType contentTypeToUse = mediaType; MediaType contentTypeToUse = mediaType;
...@@ -119,9 +121,7 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> { ...@@ -119,9 +121,7 @@ public class EncoderHttpMessageWriter<T> implements HttpMessageWriter<T> {
* @return the content type, or {@code null} * @return the content type, or {@code null}
*/ */
protected MediaType getDefaultContentType(ResolvableType elementType) { protected MediaType getDefaultContentType(ResolvableType elementType) {
return writableMediaTypes.stream() return this.mediaTypes.stream().filter(MediaType::isConcrete).findFirst().orElse(null);
.filter(MediaType::isConcrete)
.findFirst().orElse(null);
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册