提交 3e096ce8 编写于 作者: R Rossen Stoyanchev

Improve javadoc on reactive classes

Ensure type-level Javadoc in every class, comply with guidelines for
80 char on Javadoc, and minor polish.
上级 7a0c2422
......@@ -28,6 +28,8 @@ import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.util.MimeType;
/**
* Abstract base class for {@link Decoder} implementations.
*
* @author Sebastien Deleuze
* @author Arjen Poutsma
* @since 5.0
......@@ -36,6 +38,7 @@ public abstract class AbstractDecoder<T> implements Decoder<T> {
private List<MimeType> decodableMimeTypes = Collections.emptyList();
protected AbstractDecoder(MimeType... supportedMimeTypes) {
this.decodableMimeTypes = Arrays.asList(supportedMimeTypes);
}
......@@ -51,12 +54,14 @@ public abstract class AbstractDecoder<T> implements Decoder<T> {
if (mimeType == null) {
return true;
}
return this.decodableMimeTypes.stream().
anyMatch(mt -> mt.isCompatibleWith(mimeType));
return this.decodableMimeTypes.stream().anyMatch(m -> m.isCompatibleWith(mimeType));
}
@Override
public Mono<T> decodeToMono(Publisher<DataBuffer> inputStream, ResolvableType elementType, MimeType mimeType, Object... hints) {
public Mono<T> decodeToMono(Publisher<DataBuffer> inputStream, ResolvableType elementType,
MimeType mimeType, Object... hints) {
throw new UnsupportedOperationException();
}
}
......@@ -24,6 +24,8 @@ import org.springframework.core.ResolvableType;
import org.springframework.util.MimeType;
/**
* Abstract base class for {@link Decoder} implementations.
*
* @author Sebastien Deleuze
* @author Arjen Poutsma
* @since 5.0
......@@ -32,6 +34,7 @@ public abstract class AbstractEncoder<T> implements Encoder<T> {
private List<MimeType> encodableMimeTypes = Collections.emptyList();
protected AbstractEncoder(MimeType... supportedMimeTypes) {
this.encodableMimeTypes = Arrays.asList(supportedMimeTypes);
}
......@@ -47,8 +50,7 @@ public abstract class AbstractEncoder<T> implements Encoder<T> {
if (mimeType == null) {
return true;
}
return this.encodableMimeTypes.stream().
anyMatch(mt -> mt.isCompatibleWith(mimeType));
return this.encodableMimeTypes.stream().anyMatch(m -> m.isCompatibleWith(mimeType));
}
}
......@@ -25,21 +25,25 @@ import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.util.MimeType;
/**
* Abstract base class for {@link org.springframework.core.codec.Encoder} classes that
* can only deal with a single value.
* Abstract base class for {@link org.springframework.core.codec.Encoder}
* classes that can only deal with a single value.
*
* @author Arjen Poutsma
* @since 5.0
*/
public abstract class AbstractSingleValueEncoder<T> extends AbstractEncoder<T> {
public AbstractSingleValueEncoder(MimeType... supportedMimeTypes) {
super(supportedMimeTypes);
}
@Override
public final Flux<DataBuffer> encode(Publisher<? extends T> inputStream,
DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType,
Object... hints) {
return Flux.from(inputStream).
take(1).
concatMap(t -> {
......@@ -53,7 +57,7 @@ public abstract class AbstractSingleValueEncoder<T> extends AbstractEncoder<T> {
}
/**
* Encodes {@code T} to an output {@link DataBuffer} stream.
* Encode {@code T} to an output {@link DataBuffer} stream.
* @param t the value to process
* @param dataBufferFactory a buffer factory used to create the output
* @param type the stream element type to process
......@@ -65,5 +69,4 @@ public abstract class AbstractSingleValueEncoder<T> extends AbstractEncoder<T> {
protected abstract Flux<DataBuffer> encode(T t, DataBufferFactory dataBufferFactory,
ResolvableType type, MimeType mimeType, Object... hints) throws Exception;
}
......@@ -28,6 +28,8 @@ import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
/**
* Decoder for {@link ByteBuffer}s.
*
* @author Sebastien Deleuze
* @author Arjen Poutsma
* @since 5.0
......@@ -49,6 +51,7 @@ public class ByteBufferDecoder extends AbstractDecoder<ByteBuffer> {
@Override
public Flux<ByteBuffer> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType,
MimeType mimeType, Object... hints) {
return Flux.from(inputStream).map((dataBuffer) -> {
ByteBuffer copy = ByteBuffer.allocate(dataBuffer.readableByteCount());
copy.put(dataBuffer.asByteBuffer());
......
......@@ -28,11 +28,14 @@ import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
/**
* Encoder for {@link ByteBuffer}s.
*
* @author Sebastien Deleuze
* @since 5.0
*/
public class ByteBufferEncoder extends AbstractEncoder<ByteBuffer> {
public ByteBufferEncoder() {
super(MimeTypeUtils.ALL);
}
......
......@@ -32,17 +32,19 @@ import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
/**
* A decoder for {@link Resource}s.
* Decoder for {@link Resource}s.
*
* @author Arjen Poutsma
* @since 5.0
*/
public class ResourceDecoder extends AbstractDecoder<Resource> {
public ResourceDecoder() {
super(MimeTypeUtils.ALL);
}
@Override
public boolean canDecode(ResolvableType elementType, MimeType mimeType, Object... hints) {
Class<?> clazz = elementType.getRawClass();
......@@ -54,6 +56,7 @@ public class ResourceDecoder extends AbstractDecoder<Resource> {
@Override
public Flux<Resource> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType,
MimeType mimeType, Object... hints) {
Class<?> clazz = elementType.getRawClass();
Mono<byte[]> byteArray = Flux.from(inputStream).
......@@ -67,17 +70,13 @@ public class ResourceDecoder extends AbstractDecoder<Resource> {
if (InputStreamResource.class.equals(clazz)) {
return Flux.from(byteArray.
map(ByteArrayInputStream::new).
map(InputStreamResource::new));
return Flux.from(byteArray.map(ByteArrayInputStream::new).map(InputStreamResource::new));
}
else if (clazz.isAssignableFrom(ByteArrayResource.class)) {
return Flux.from(byteArray.
map(ByteArrayResource::new));
return Flux.from(byteArray.map(ByteArrayResource::new));
}
else {
return Flux.error(new IllegalStateException(
"Unsupported resource class: " + clazz));
return Flux.error(new IllegalStateException("Unsupported resource class: " + clazz));
}
}
}
......@@ -32,7 +32,8 @@ import org.springframework.util.MimeTypeUtils;
import org.springframework.util.StreamUtils;
/**
* An encoder for {@link Resource}s.
* Encoder for {@link Resource}s.
*
* @author Arjen Poutsma
* @since 5.0
*/
......@@ -40,8 +41,10 @@ public class ResourceEncoder extends AbstractSingleValueEncoder<Resource> {
public static final int DEFAULT_BUFFER_SIZE = StreamUtils.BUFFER_SIZE;
private final int bufferSize;
public ResourceEncoder() {
this(DEFAULT_BUFFER_SIZE);
}
......@@ -52,17 +55,17 @@ public class ResourceEncoder extends AbstractSingleValueEncoder<Resource> {
this.bufferSize = bufferSize;
}
@Override
public boolean canEncode(ResolvableType elementType, MimeType mimeType, Object... hints) {
Class<?> clazz = elementType.getRawClass();
return (super.canEncode(elementType, mimeType, hints) &&
Resource.class.isAssignableFrom(clazz));
return (super.canEncode(elementType, mimeType, hints) && Resource.class.isAssignableFrom(clazz));
}
@Override
protected Flux<DataBuffer> encode(Resource resource,
DataBufferFactory dataBufferFactory,
protected Flux<DataBuffer> encode(Resource resource, DataBufferFactory dataBufferFactory,
ResolvableType type, MimeType mimeType, Object... hints) throws IOException {
InputStream is = resource.getInputStream();
return DataBufferUtils.read(is, dataBufferFactory, bufferSize);
}
......
......@@ -38,6 +38,7 @@ public class StringEncoder extends AbstractEncoder<String> {
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
public StringEncoder() {
super(new MimeType("text", "plain", DEFAULT_CHARSET));
}
......@@ -51,8 +52,9 @@ public class StringEncoder extends AbstractEncoder<String> {
@Override
public Flux<DataBuffer> encode(Publisher<? extends String> inputStream,
DataBufferFactory bufferFactory, ResolvableType elementType, MimeType mimeType,
Object... hints) {
DataBufferFactory bufferFactory, ResolvableType elementType,
MimeType mimeType, Object... hints) {
Charset charset;
if (mimeType != null && mimeType.getCharset() != null) {
charset = mimeType.getCharset();
......
......@@ -27,11 +27,15 @@ import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
/**
* Converter to adapt {@link CompletableFuture} to Reactive Streams and
* Reactor {@link Mono}.
*
* @author Sebastien Deleuze
* @since 5.0
*/
public class MonoToCompletableFutureConverter implements GenericConverter {
@Override
public Set<GenericConverter.ConvertiblePair> getConvertibleTypes() {
Set<GenericConverter.ConvertiblePair> pairs = new LinkedHashSet<>(2);
......@@ -40,6 +44,7 @@ public class MonoToCompletableFutureConverter implements GenericConverter {
return pairs;
}
@Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
if (source == null) {
......
......@@ -31,6 +31,9 @@ import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.GenericConverter;
/**
* Converter to adapt RxJava1 {@link Observable}, {@link Single}, and
* {@link Completable} to Reactive Streams and Reactor types.
*
* @author Stephane Maldini
* @author Sebastien Deleuze
* @since 5.0
......
......@@ -19,8 +19,8 @@ package org.springframework.core.io.buffer;
import java.nio.ByteBuffer;
/**
* A factory for {@link DataBuffer}s, allowing for allocation and wrapping of data
* buffers.
* A factory for {@link DataBuffer}s,allowing for allocation and wrapping of
* data buffers.
*
* @author Arjen Poutsma
* @see DataBuffer
......@@ -29,22 +29,24 @@ import java.nio.ByteBuffer;
public interface DataBufferFactory {
/**
* Allocates a data buffer of a default initial capacity. Depending on the underlying
* implementation and its configuration, this will be heap-based or direct buffer.
* Allocate a data buffer of a default initial capacity. Depending on the
* underlying implementation and its configuration, this will be heap-based
* or direct buffer.
* @return the allocated buffer
*/
DataBuffer allocateBuffer();
/**
* Allocates a data buffer of the given initial capacity. Depending on the underlying
* implementation and its configuration, this will be heap-based or direct buffer.
* @param initialCapacity the initial capacity of the buffer to allocateBuffer
* Allocate a data buffer of the given initial capacity. Depending on the
* underlying implementation and its configuration, this will be heap-based
* or direct buffer.
* @param initialCapacity the initial capacity of the buffer to allocate
* @return the allocated buffer
*/
DataBuffer allocateBuffer(int initialCapacity);
/**
* Wraps the given {@link ByteBuffer} in a {@code DataBuffer}.
* Wrap the given {@link ByteBuffer} in a {@code DataBuffer}.
* @param byteBuffer the NIO byte buffer to wrap
* @return the wrapped buffer
*/
......
......@@ -47,8 +47,9 @@ public class DefaultDataBuffer implements DataBuffer {
private int writePosition;
/**
* Creates a new {@code DefaultDataBuffer} based on the given {@code ByteBuffer}. Both
* reading and writing position of this buffer are based on the current {@linkplain
* Create a new {@code DefaultDataBuffer} based on the given
* {@code ByteBuffer}. Both reading and writing position of this buffer are
* based on the current {@linkplain
* ByteBuffer#position() position} of the given buffer.
* @param byteBuffer the buffer to base this buffer on
*/
......
......@@ -22,8 +22,8 @@ import org.springframework.util.Assert;
/**
* Default implementation of the {@code DataBufferFactory} interface. Allows for
* specification of the default initial capacity at construction time, as well as whether
* heap-based or direct buffers are to be preferred.
* specification of the default initial capacity at construction time, as well
* as whether heap-based or direct buffers are to be preferred.
*
* @author Arjen Poutsma
* @since 5.0
......@@ -42,6 +42,7 @@ public class DefaultDataBufferFactory implements DataBufferFactory {
private final int defaultInitialCapacity;
/**
* Creates a new {@code DefaultDataBufferFactory} with default settings.
*/
......@@ -50,21 +51,23 @@ public class DefaultDataBufferFactory implements DataBufferFactory {
}
/**
* Creates a new {@code DefaultDataBufferFactory}, indicating whether direct buffers
* should be created by {@link #allocateBuffer()} and {@link #allocateBuffer(int)}.
* @param preferDirect {@code true} if direct buffers are to be preferred; {@code
* false} otherwise
* Creates a new {@code DefaultDataBufferFactory}, indicating whether direct
* buffers should be created by {@link #allocateBuffer()} and
* {@link #allocateBuffer(int)}.
* @param preferDirect {@code true} if direct buffers are to be preferred;
* {@code false} otherwise
*/
public DefaultDataBufferFactory(boolean preferDirect) {
this(preferDirect, DEFAULT_INITIAL_CAPACITY);
}
/**
* Creates a new {@code DefaultDataBufferFactory}, indicating whether direct buffers
* should be created by {@link #allocateBuffer()} and {@link #allocateBuffer(int)},
* and what the capacity is to be used for {@link #allocateBuffer()}.
* @param preferDirect {@code true} if direct buffers are to be preferred; {@code
* false} otherwise
* Creates a new {@code DefaultDataBufferFactory}, indicating whether direct
* buffers should be created by {@link #allocateBuffer()} and
* {@link #allocateBuffer(int)}, and what the capacity is to be used for
* {@link #allocateBuffer()}.
* @param preferDirect {@code true} if direct buffers are to be preferred;
* {@code false} otherwise
*/
public DefaultDataBufferFactory(boolean preferDirect, int defaultInitialCapacity) {
Assert.isTrue(defaultInitialCapacity > 0,
......@@ -73,6 +76,7 @@ public class DefaultDataBufferFactory implements DataBufferFactory {
this.defaultInitialCapacity = defaultInitialCapacity;
}
@Override
public DefaultDataBuffer allocateBuffer() {
return allocateBuffer(this.defaultInitialCapacity);
......
......@@ -22,8 +22,8 @@ import java.nio.ByteBuffer;
import java.util.function.IntPredicate;
/**
* Empty {@link DataBuffer} that indicates to the file or the socket writing it that
* previously buffered data should be flushed.
* Empty {@link DataBuffer} that indicates to the file or the socket writing it
* that previously buffered data should be flushed.
*
* @author Sebastien Deleuze
* @since 5.0
......
......@@ -32,8 +32,8 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
/**
* Implementation of the {@code DataBuffer} interface that wraps a Netty {@link ByteBuf}.
* Typically constructed using the {@link NettyDataBufferFactory}.
* Implementation of the {@code DataBuffer} interface that wraps a Netty
* {@link ByteBuf}. Typically constructed with {@link NettyDataBufferFactory}.
*
* @author Arjen Poutsma
* @since 5.0
......
......@@ -37,6 +37,7 @@ public class NettyDataBufferFactory implements DataBufferFactory {
private final ByteBufAllocator byteBufAllocator;
/**
* Creates a new {@code NettyDataBufferFactory} based on the given factory.
* @param byteBufAllocator the factory to use
......@@ -49,6 +50,7 @@ public class NettyDataBufferFactory implements DataBufferFactory {
this.byteBufAllocator = byteBufAllocator;
}
@Override
public NettyDataBuffer allocateBuffer() {
ByteBuf byteBuf = this.byteBufAllocator.buffer();
......
......@@ -17,8 +17,8 @@
package org.springframework.core.io.buffer;
/**
* Extension of {@link DataBuffer} that allows for buffer that share a memory pool.
* Introduces methods for reference counting.
* Extension of {@link DataBuffer} that allows for buffer that share a memory
* pool. Introduces methods for reference counting.
*
* @author Arjen Poutsma
* @since 5.0
......@@ -32,8 +32,8 @@ public interface PooledDataBuffer extends DataBuffer {
PooledDataBuffer retain();
/**
* Decreases the reference count for this buffer by one, and releases it once the
* count reaches zero.
* Decreases the reference count for this buffer by one, and releases it
* once the count reaches zero.
* @return {@code true} if the buffer was released; {@code false} otherwise.
*/
boolean release();
......
......@@ -89,8 +89,8 @@ public abstract class DataBufferUtils {
/**
* Relays buffers from the given {@link Publisher} until the total
* {@linkplain DataBuffer#readableByteCount() byte count} reaches the given maximum
* byte count, or until the publisher is complete.
* {@linkplain DataBuffer#readableByteCount() byte count} reaches the given
* maximum byte count, or until the publisher is complete.
* @param publisher the publisher to filter
* @param maxByteCount the maximum byte count
* @return a flux whose maximum byte count is {@code maxByteCount}
......
......@@ -21,8 +21,8 @@ import java.util.Set;
import org.springframework.http.MediaType;
/**
* An extension of {@link RequestedContentTypeResolver} that maintains a mapping between
* keys (e.g. file extension, query parameter) and media types.
* An extension of {@link RequestedContentTypeResolver} that maintains a mapping
* between keys (e.g. file extension, query parameter) and media types.
*
* @author Rossen Stoyanchev
* @since 5.0
......
......@@ -27,8 +27,8 @@ import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.ServerWebExchange;
/**
* A {@link RequestedContentTypeResolver} that extracts the media type lookup key from a
* known query parameter named "format" by default.
* A {@link RequestedContentTypeResolver} that extracts the media type lookup
* key from a known query parameter named "format" by default.
*
* @author Rossen Stoyanchev
* @since 5.0
......
......@@ -31,8 +31,8 @@ import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.WebUtils;
/**
* A {@link RequestedContentTypeResolver} that extracts the file extension from the
* request path and uses that as the media type lookup key.
* A {@link RequestedContentTypeResolver} that extracts the file extension from
* the request path and uses that as the media type lookup key.
*
* <p>If the file extension is not found in the explicit registrations provided
* to the constructor, the Java Activation Framework (JAF) is used as a fallback
......
......@@ -22,7 +22,8 @@ import org.springframework.web.server.NotAcceptableStatusException;
import org.springframework.web.server.ServerWebExchange;
/**
* Strategy for resolving the requested media types for a {@code ServerWebExchange}.
* Strategy for resolving the requested media types for a
* {@code ServerWebExchange}.
*
* @author Rossen Stoyanchev
* @since 5.0
......
......@@ -28,9 +28,9 @@ import org.springframework.util.CollectionUtils;
/**
* Factory to create a {@link CompositeContentTypeResolver} and configure it with
* one or more {@link RequestedContentTypeResolver} instances with build style methods.
* The following table shows methods, resulting strategy instances, and if in
* use by default:
* one or more {@link RequestedContentTypeResolver} instances with build style
* methods. The following table shows methods, resulting strategy instances, and
* if in use by default:
*
* <table>
* <tr>
......@@ -65,9 +65,10 @@ import org.springframework.util.CollectionUtils;
* </tr>
* </table>
*
* <p>The order in which resolvers are configured is fixed. Config methods may only
* turn individual resolvers on or off. If you need a custom order for any
* reason simply instantiate {@code {@link CompositeContentTypeResolver}} directly.
* <p>The order in which resolvers are configured is fixed. Config methods may
* only turn individual resolvers on or off. If you need a custom order for any
* reason simply instantiate {@code {@link CompositeContentTypeResolver}}
* directly.
*
* <p>For the path extension and parameter resolvers you may explicitly add
* {@link #mediaTypes(Map)}. This will be used to resolve path extensions or a
......
......@@ -40,6 +40,9 @@ import org.springframework.web.server.ServerWebExchange;
/**
* Extension of HandlerMethod that can invoke the target method after resolving
* its method arguments.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
......
......@@ -34,6 +34,7 @@ import org.springframework.web.reactive.HandlerResult;
import org.springframework.web.server.ServerWebExchange;
/**
* Base class for {@link View} implementations.
*
* @author Rossen Stoyanchev
* @since 5.0
......
......@@ -47,6 +47,7 @@ public abstract class AbstractClientHttpRequest implements ClientHttpRequest {
private final List<Supplier<? extends Mono<Void>>> beforeCommitActions = new ArrayList<>(4);
public AbstractClientHttpRequest() {
this(new HttpHeaders());
}
......@@ -57,6 +58,7 @@ public abstract class AbstractClientHttpRequest implements ClientHttpRequest {
this.cookies = new LinkedMultiValueMap<>();
}
@Override
public HttpHeaders getHeaders() {
if (State.COMITTED.equals(this.state.get())) {
......
......@@ -23,10 +23,9 @@ import reactor.core.publisher.Mono;
import org.springframework.http.HttpMethod;
/**
* Client abstraction for HTTP client runtimes.
* {@link ClientHttpConnector} drives the underlying HTTP client implementation
* so as to connect to the origin server and provide all the necessary infrastructure
* to send the actual {@link ClientHttpRequest} and receive the {@link ClientHttpResponse}
* Abstraction over HTTP clients driving the underlying HTTP client to connect
* to the origin server and provide all necessary infrastructure to send a
* {@link ClientHttpRequest} and receive a {@link ClientHttpResponse}.
*
* @author Brian Clozel
* @since 5.0
......@@ -34,16 +33,16 @@ import org.springframework.http.HttpMethod;
public interface ClientHttpConnector {
/**
* Connect to the origin server using the given {@code HttpMethod} and {@code URI},
* then apply the given {@code requestCallback} on the {@link ClientHttpRequest}
* once the connection has been established.
* Connect to the origin server using the given {@code HttpMethod} and
* {@code URI}, then apply the given {@code requestCallback} on the
* {@link ClientHttpRequest} once the connection has been established.
* <p>Return a publisher of the {@link ClientHttpResponse}.
*
* @param method the HTTP request method
* @param uri the HTTP request URI
* @param requestCallback a function that prepares and writes the request,
* returning a publisher that signals when it's done interacting with the request.
* Implementations should return a {@code Mono<Void>} by calling
* returning a publisher that signals when it's done interacting with the
* request. Implementations should return a {@code Mono<Void>} by calling
* {@link ClientHttpRequest#writeWith} or {@link ClientHttpRequest#setComplete}.
* @return a publisher of the {@link ClientHttpResponse}
*/
......
......@@ -24,7 +24,7 @@ import org.springframework.http.ReactiveHttpOutputMessage;
import org.springframework.util.MultiValueMap;
/**
* Represents a reactive client-side HTTP request.
* Represents a client-side reactive HTTP request.
*
* @author Arjen Poutsma
* @author Brian Clozel
......
......@@ -22,7 +22,7 @@ import org.springframework.http.ResponseCookie;
import org.springframework.util.MultiValueMap;
/**
* Represents a reactive client-side HTTP response.
* Represents a client-side reactive HTTP response.
*
* @author Arjen Poutsma
* @since 5.0
......
......@@ -47,4 +47,5 @@ public class ReactorClientHttpConnector implements ClientHttpConnector {
.otherwise(HttpException.class, exc -> Mono.just(exc.getChannel()))
.map(httpInbound -> new ReactorClientHttpResponse(httpInbound));
}
}
\ No newline at end of file
......@@ -33,7 +33,7 @@ import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.http.HttpMethod;
/**
* {@link ClientHttpRequest} implementation for the Reactor-Netty HTTP client
* {@link ClientHttpRequest} implementation for the Reactor-Netty HTTP client.
*
* @author Brian Clozel
* @since 5.0
......@@ -49,6 +49,7 @@ public class ReactorClientHttpRequest extends AbstractClientHttpRequest {
private final NettyDataBufferFactory bufferFactory;
public ReactorClientHttpRequest(HttpMethod httpMethod, URI uri, HttpClientRequest httpRequest) {
this.httpMethod = httpMethod;
this.uri = uri;
......@@ -56,6 +57,7 @@ public class ReactorClientHttpRequest extends AbstractClientHttpRequest {
this.bufferFactory = new NettyDataBufferFactory(httpRequest.delegate().alloc());
}
@Override
public DataBufferFactory bufferFactory() {
return this.bufferFactory;
......
......@@ -31,7 +31,7 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
/**
* {@link ClientHttpResponse} implementation for the Reactor-Netty HTTP client
* {@link ClientHttpResponse} implementation for the Reactor-Netty HTTP client.
*
* @author Brian Clozel
* @see reactor.io.netty.http.HttpClient
......@@ -43,11 +43,13 @@ public class ReactorClientHttpResponse implements ClientHttpResponse {
private final HttpInbound response;
public ReactorClientHttpResponse(HttpInbound response) {
this.response = response;
this.dataBufferFactory = new NettyDataBufferFactory(response.delegate().alloc());
}
@Override
public Flux<DataBuffer> getBody() {
return response.receive()
......
......@@ -20,10 +20,9 @@ import org.springframework.http.MediaType;
import org.springframework.http.codec.SseEventEncoder;
/**
* Represent a Server-Sent Event.
*
* <p>{@code Flux<SseEvent>} is Spring Web Reactive equivalent to Spring MVC
* {@code SseEmitter} type. It allows to send Server-Sent Events in a reactive way.
* Representation for a Server-Sent Event for use with Spring's reactive Web
* support. {@code Flux<SseEvent>} or {@code Observable<SseEvent>} is the
* reactive equivalent to Spring MVC's {@code SseEmitter}.
*
* @author Sebastien Deleuze
* @since 5.0
......@@ -44,6 +43,7 @@ public class SseEvent {
private String comment;
/**
* Create an empty instance.
*/
......@@ -65,6 +65,7 @@ public class SseEvent {
this.mediaType = mediaType;
}
/**
* Set the {@code id} SSE field
*/
......
......@@ -36,8 +36,10 @@ import org.springframework.util.Assert;
import org.springframework.util.MimeType;
/**
* An encoder for {@link SseEvent}s that also supports any other kind of {@link Object}
* (in that case, the object will be the data of the {@link SseEvent}).
* Encoder that supports a stream of {@link SseEvent}s and also plain
* {@link Object}s which is the same as an {@link SseEvent} with data
* only.
*
* @author Sebastien Deleuze
* @since 5.0
*/
......
......@@ -44,7 +44,8 @@ import org.springframework.util.MimeTypeUtils;
import org.springframework.util.xml.StaxUtils;
/**
* Decode from a bytes stream of XML elements to a stream of {@code Object} (POJO).
* Decode from a bytes stream containing XML elements to a stream of
* {@code Object}s (POJOs).
*
* @author Sebastien Deleuze
* @author Arjen Poutsma
......@@ -66,10 +67,12 @@ public class Jaxb2Decoder extends AbstractDecoder<Object> {
private final JaxbContextContainer jaxbContexts = new JaxbContextContainer();
public Jaxb2Decoder() {
super(MimeTypeUtils.APPLICATION_XML, MimeTypeUtils.TEXT_XML);
}
@Override
public boolean canDecode(ResolvableType elementType, MimeType mimeType, Object... hints) {
if (super.canDecode(elementType, mimeType, hints)) {
......@@ -85,6 +88,7 @@ public class Jaxb2Decoder extends AbstractDecoder<Object> {
@Override
public Flux<Object> decode(Publisher<DataBuffer> inputStream, ResolvableType elementType,
MimeType mimeType, Object... hints) {
Class<?> outputClass = elementType.getRawClass();
Flux<XMLEvent> xmlEventFlux =
this.xmlEventDecoder.decode(inputStream, null, mimeType);
......
......@@ -34,7 +34,7 @@ import org.springframework.util.MimeType;
import org.springframework.util.MimeTypeUtils;
/**
* Encode from an {@code Object} stream to a byte stream of XML elements.
* Encode from {@code Object} stream to a byte stream containing XML elements.
*
* @author Sebastien Deleuze
* @author Arjen Poutsma
......
......@@ -31,9 +31,11 @@ import org.springframework.util.Assert;
*/
final class JaxbContextContainer {
private final ConcurrentMap<Class<?>, JAXBContext> jaxbContexts =
new ConcurrentHashMap<>(64);
public Marshaller createMarshaller(Class<?> clazz) throws JAXBException {
JAXBContext jaxbContext = getJaxbContext(clazz);
return jaxbContext.createMarshaller();
......
......@@ -34,8 +34,8 @@ import org.springframework.core.io.buffer.DataBuffer;
/**
* Abstract base class for {@code Publisher} implementations that bridge between
* event-listener APIs and Reactive Streams. Specifically, base class for the Servlet 3.1
* and Undertow support.
* event-listener APIs and Reactive Streams. Specifically, base class for the
* Servlet 3.1 and Undertow support.
*
* @author Arjen Poutsma
* @since 5.0
......
......@@ -35,8 +35,9 @@ import org.springframework.util.Assert;
/**
* Abstract base class for {@code Subscriber} implementations that bridge between
* event-listener APIs and Reactive Streams. Specifically, base class for the Servlet 3.1
* and Undertow support.
* event-listener APIs and Reactive Streams. Specifically, base class for the
* Servlet 3.1 and Undertow support.
*
* @author Arjen Poutsma
* @since 5.0
* @see ServletServerHttpRequest
......
......@@ -25,28 +25,27 @@ import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.util.Assert;
/**
* Adapt {@link HttpHandler} to the Reactor Netty {@link ChannelHandler}.
*
* @author Stephane Maldini
* @since 5.0
*/
public class ReactorHttpHandlerAdapter
implements ChannelHandler<ByteBuf, ByteBuf, HttpChannel> {
public class ReactorHttpHandlerAdapter implements ChannelHandler<ByteBuf, ByteBuf, HttpChannel> {
private final HttpHandler httpHandler;
public ReactorHttpHandlerAdapter(HttpHandler httpHandler) {
Assert.notNull(httpHandler, "'httpHandler' is required.");
this.httpHandler = httpHandler;
}
@Override
public Mono<Void> apply(HttpChannel channel) {
NettyDataBufferFactory dataBufferFactory =
new NettyDataBufferFactory(channel.delegate().alloc());
ReactorServerHttpRequest adaptedRequest =
new ReactorServerHttpRequest(channel, dataBufferFactory);
ReactorServerHttpResponse adaptedResponse =
new ReactorServerHttpResponse(channel, dataBufferFactory);
NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(channel.delegate().alloc());
ReactorServerHttpRequest adaptedRequest = new ReactorServerHttpRequest(channel, bufferFactory);
ReactorServerHttpResponse adaptedResponse = new ReactorServerHttpResponse(channel, bufferFactory);
return this.httpHandler.handle(adaptedRequest, adaptedResponse);
}
......
......@@ -28,6 +28,7 @@ import reactor.core.publisher.Operators;
/**
* Publisher returned from {@link ServerHttpResponse#writeWith(Publisher)}.
*
* @author Arjen Poutsma
* @since 5.0
*/
......
......@@ -28,6 +28,8 @@ import org.springframework.core.io.buffer.NettyDataBufferFactory;
import org.springframework.util.Assert;
/**
* Adapt {@link HttpHandler} to the RxNetty {@link RequestHandler}.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
......@@ -35,20 +37,18 @@ public class RxNettyHttpHandlerAdapter implements RequestHandler<ByteBuf, ByteBu
private final HttpHandler httpHandler;
public RxNettyHttpHandlerAdapter(HttpHandler httpHandler) {
Assert.notNull(httpHandler, "'httpHandler' is required");
this.httpHandler = httpHandler;
}
@Override
public Observable<Void> handle(HttpServerRequest<ByteBuf> request, HttpServerResponse<ByteBuf> response) {
NettyDataBufferFactory dataBufferFactory =
new NettyDataBufferFactory(response.unsafeNettyChannel().alloc());
RxNettyServerHttpRequest adaptedRequest =
new RxNettyServerHttpRequest(request, dataBufferFactory);
RxNettyServerHttpResponse adaptedResponse =
new RxNettyServerHttpResponse(response, dataBufferFactory);
NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(response.unsafeNettyChannel().alloc());
RxNettyServerHttpRequest adaptedRequest = new RxNettyServerHttpRequest(request, bufferFactory);
RxNettyServerHttpResponse adaptedResponse = new RxNettyServerHttpResponse(response, bufferFactory);
Publisher<Void> result = this.httpHandler.handle(adaptedRequest, adaptedResponse);
return RxJava1Adapter.publisherToObservable(result);
}
......
......@@ -34,6 +34,9 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.util.Assert;
/**
* Adapt {@link HttpHandler} to an {@link HttpServlet} using Servlet Async
* support and Servlet 3.1 Non-blocking I/O.
*
* @author Arjen Poutsma
* @author Rossen Stoyanchev
* @since 5.0
......@@ -54,6 +57,7 @@ public class ServletHttpHandlerAdapter extends HttpServlet {
private int bufferSize = DEFAULT_BUFFER_SIZE;
public void setHandler(HttpHandler handler) {
Assert.notNull(handler, "'handler' must not be null");
this.handler = handler;
......
......@@ -43,6 +43,7 @@ import org.springframework.util.StringUtils;
/**
* Adapt {@link ServerHttpRequest} to the Servlet {@link HttpServletRequest}.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
......
......@@ -38,6 +38,7 @@ import org.springframework.util.Assert;
/**
* Adapt {@link ServerHttpResponse} to the Servlet {@link HttpServletResponse}.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
......
......@@ -26,6 +26,8 @@ import org.springframework.core.io.buffer.DataBufferFactory;
import org.springframework.util.Assert;
/**
* Adapt {@link HttpHandler} to the Undertow {@link io.undertow.server.HttpHandler}.
*
* @author Marek Hawrylczak
* @author Rossen Stoyanchev
* @author Arjen Poutsma
......@@ -40,14 +42,15 @@ public class UndertowHttpHandlerAdapter implements io.undertow.server.HttpHandle
private final DataBufferFactory dataBufferFactory;
public UndertowHttpHandlerAdapter(HttpHandler delegate,
DataBufferFactory dataBufferFactory) {
public UndertowHttpHandlerAdapter(HttpHandler delegate, DataBufferFactory dataBufferFactory) {
Assert.notNull(delegate, "'delegate' is required");
Assert.notNull(dataBufferFactory, "'dataBufferFactory' must not be null");
this.delegate = delegate;
this.dataBufferFactory = dataBufferFactory;
}
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
......
......@@ -39,7 +39,7 @@ import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
/**
* Adapt {@link ServerHttpRequest} to the Underow {@link HttpServerExchange}.
* Adapt {@link ServerHttpRequest} to the Undertow {@link HttpServerExchange}.
*
* @author Marek Hawrylczak
* @author Rossen Stoyanchev
......
......@@ -42,6 +42,7 @@ import org.springframework.util.Assert;
/**
* Adapt {@link ServerHttpResponse} to the Undertow {@link HttpServerExchange}.
*
* @author Marek Hawrylczak
* @author Rossen Stoyanchev
* @author Arjen Poutsma
......
......@@ -22,11 +22,11 @@ import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.http.converter.reactive.HttpMessageConverter;
/**
* A {@code BodyExtractor} extracts the content of a raw {@link ClientHttpResponse},
* decoding the response body and using a target composition API.
* Contract to extract the content of a raw {@link ClientHttpResponse} decoding
* the response body and using a target composition API.
*
* <p>See static factory methods in {@link ResponseExtractors}
* and {@link org.springframework.web.client.reactive.support.RxJava1ResponseExtractors}.
* <p>See static factory methods in {@link ResponseExtractors} and
* {@link org.springframework.web.client.reactive.support.RxJava1ResponseExtractors}.
*
* @author Brian Clozel
* @since 5.0
......@@ -40,4 +40,5 @@ public interface BodyExtractor<T> {
* @return the relevant content
*/
T extract(ClientHttpResponse clientResponse, List<HttpMessageConverter<?>> messageConverters);
}
......@@ -27,15 +27,18 @@ import org.springframework.http.HttpMethod;
import org.springframework.util.MultiValueMap;
/**
* Holds all the application information required to build an actual HTTP client request.
* <p>The request body is materialized by a {@code Publisher} of Objects and their type
* by a {@code ResolvableType} instance; it should be later converted to a
* {@code Publisher<DataBuffer>} to be written to the actual HTTP client request.
* Simple container for application-level information required to perform an
* HTTP client request.
*
* <p>The request body is provided through a {@code Publisher<Object>} where the
* type of each Object is indicated through a {@link ResolvableType} which
* subsequently is used to correctly serialize into the
* {@code Publisher<DataBuffer>} actually written to request body.
*
* @author Brian Clozel
* @since 5.0
*/
public class ClientWebRequest {
public class ClientWebRequest {
protected final HttpMethod httpMethod;
......@@ -55,6 +58,7 @@ public class ClientWebRequest {
this.url = url;
}
public HttpMethod getMethod() {
return httpMethod;
}
......
......@@ -17,7 +17,7 @@
package org.springframework.web.client.reactive;
/**
* Build {@link ClientWebRequest}s
* Build {@link ClientWebRequest}s.
*
* @author Brian Clozel
* @since 5.0
......
......@@ -20,7 +20,8 @@ package org.springframework.web.client.reactive;
import org.springframework.http.HttpMethod;
/**
* Static factory methods for {@link DefaultClientWebRequestBuilder ClientWebRequestBuilders}
* Static factory methods for {@link DefaultClientWebRequestBuilder
* ClientWebRequestBuilders}.
*
* @author Brian Clozel
* @since 5.0
......@@ -47,7 +48,6 @@ public abstract class ClientWebRequestBuilders {
return new DefaultClientWebRequestBuilder(HttpMethod.POST, urlTemplate, urlVariables);
}
/**
* Create a {@link DefaultClientWebRequestBuilder} for a PUT request.
*
......
......@@ -17,8 +17,9 @@
package org.springframework.web.client.reactive;
/**
* Allow post processing and/or wrapping the {@link ClientWebRequest} before
* it's sent to the origin server.
* Contract to post-process the {@link ClientWebRequest} after it is created
* an initialized in order to mofidy or even wrap it. This may be used for
* example to pre-package specific modifications to the request.
*
* @author Rob Winch
* @author Brian Clozel
......@@ -28,10 +29,10 @@ package org.springframework.web.client.reactive;
public interface ClientWebRequestPostProcessor {
/**
* Implementations can modify and/or wrap the {@link ClientWebRequest} passed in
* and return it
*
* Implementations can modify and/or wrap the {@link ClientWebRequest}
* passed in and return it
* @param request the {@link ClientWebRequest} to be modified and/or wrapped.
*/
ClientWebRequest postProcess(ClientWebRequest request);
}
......@@ -41,7 +41,7 @@ import org.springframework.web.util.UriTemplateHandler;
* Builds a {@link ClientHttpRequest} using a {@link Publisher}
* as request body.
*
* <p>See static factory methods in {@link ClientWebRequestBuilders}
* <p>See static factory methods in {@link ClientWebRequestBuilders}.
*
* @author Brian Clozel
* @since 5.0
......
......@@ -22,8 +22,8 @@ import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.http.converter.reactive.HttpMessageConverter;
/**
* Strategy interface used by the {@link WebClient} to handle
* errors in {@link ClientHttpResponse}s if needed.
* Strategy interface used by the {@link WebClient} to handle errors in
* {@link ClientHttpResponse}s if needed.
*
* @author Brian Clozel
* @see DefaultResponseErrorHandler
......@@ -33,8 +33,9 @@ public interface ResponseErrorHandler {
/**
* Handle the error in the given response.
* Implementations will typically inspect the {@link ClientHttpResponse#getStatusCode() HttpStatus}
* of the response and throw {@link WebClientException}s in case of errors.
* Implementations will typically inspect the
* {@link ClientHttpResponse#getStatusCode() HttpStatus} of the response and
* throw {@link WebClientException}s in case of errors.
*/
void handleError(ClientHttpResponse response, List<HttpMessageConverter<?>> messageConverters);
......
......@@ -55,21 +55,23 @@ import reactor.core.publisher.Mono;
* <p>Here is a simple example of a GET request:
*
* <pre class="code">
* static imports: ClientWebRequestBuilder.*, ResponseExtractors.*
*
* // should be shared between HTTP calls
* WebClient client = new WebClient(new ReactorHttpClient());
*
* Mono&lt;String&gt; result = client
* .perform(ClientWebRequestBuilders.get("http://example.org/resource")
* .accept(MediaType.TEXT_PLAIN))
* .extract(ResponseExtractors.body(String.class));
* .perform(get("http://example.org/resource").accept(MediaType.TEXT_PLAIN))
* .extract(body(String.class));
* </pre>
*
* <p>This Web client relies on
* <p>This Web client relies on the following:
* <ul>
* <li>an {@link ClientHttpConnector} implementation that drives the underlying library (e.g. Reactor-Netty)</li>
* <li>a {@link ClientWebRequestBuilder} which creates a Web request with a builder API (see
* {@link ClientWebRequestBuilders})</li>
* <li>an {@link ResponseExtractor} which extracts the relevant part of the server
* <li>{@link ClientHttpConnector} implementation to drive the underlying
* library (e.g. Reactor-Netty)</li>
* <li>{@link ClientWebRequestBuilder} to create a Web request with a builder
* API (see {@link ClientWebRequestBuilders})</li>
* <li>{@link ResponseExtractor} to extract the relevant part of the server
* response with the composition API of choice (see {@link ResponseExtractors}</li>
* </ul>
*
......
......@@ -18,7 +18,6 @@ package org.springframework.web.client.reactive;
import java.util.List;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.http.converter.reactive.HttpMessageConverter;
......@@ -31,15 +30,21 @@ import org.springframework.http.converter.reactive.HttpMessageConverter;
@SuppressWarnings("serial")
public class WebClientErrorException extends WebClientResponseException {
/**
* Construct a new instance of {@code HttpClientErrorException} based on a {@link ClientHttpResponse}
* and {@link HttpMessageConverter}s to optionally help decoding the response body
* @param clientResponse the HTTP response
* @param messageConverters the message converters that may decode the HTTP response body
* Construct a new instance of {@code HttpClientErrorException} based on a
* {@link ClientHttpResponse} and {@link HttpMessageConverter}s to optionally
* help decoding the response body
*
* @param response the HTTP response
* @param converters the message converters that may decode the HTTP response body
*/
public WebClientErrorException(ClientHttpResponse clientResponse,
List<HttpMessageConverter<?>> messageConverters) {
super(clientResponse.getStatusCode().value() + " " + clientResponse.getStatusCode().getReasonPhrase(),
clientResponse, messageConverters);
public WebClientErrorException(ClientHttpResponse response, List<HttpMessageConverter<?>> converters) {
super(initMessage(response), response, converters);
}
private static String initMessage(ClientHttpResponse response) {
return response.getStatusCode().value() + " " + response.getStatusCode().getReasonPhrase();
}
}
......@@ -19,8 +19,7 @@ package org.springframework.web.client.reactive;
import org.springframework.core.NestedRuntimeException;
/**
* Base class for exceptions thrown by {@link WebClient} whenever
* it encounters errors.
* Base class for exceptions thrown by {@link WebClient}.
*
* @author Brian Clozel
* @since 5.0
......@@ -35,4 +34,5 @@ public class WebClientException extends NestedRuntimeException {
public WebClientException(String msg, Throwable cause) {
super(msg, cause);
}
}
......@@ -24,7 +24,8 @@ import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.http.converter.reactive.HttpMessageConverter;
/**
* Base class for exceptions associated with specific HTTP client response status codes.
* Base class for exceptions associated with specific HTTP client response
* status codes.
*
* @author Brian Clozel
* @since 5.0
......@@ -36,6 +37,7 @@ public class WebClientResponseException extends WebClientException {
private final List<HttpMessageConverter<?>> messageConverters;
/**
* Construct a new instance of {@code WebClientResponseException} with the given response data
* @param message the given error message
......@@ -49,6 +51,7 @@ public class WebClientResponseException extends WebClientException {
this.messageConverters = messageConverters;
}
/**
* Return the HTTP status
*/
......
......@@ -47,4 +47,5 @@ public interface WebResponseActions {
* </pre>
*/
<T> T extract(ResponseExtractor<T> extractor);
}
......@@ -32,13 +32,18 @@ import org.springframework.http.converter.reactive.HttpMessageConverter;
public class WebServerErrorException extends WebClientResponseException {
/**
* Construct a new instance of {@code HttpServerErrorException} based on a {@link ClientHttpResponse}
* and {@link HttpMessageConverter}s to optionally help decoding the response body
* @param clientResponse the HTTP response
* @param messageConverters the message converters that may decode the HTTP response body
* Construct a new instance of {@code HttpServerErrorException} based on a
* {@link ClientHttpResponse} and {@link HttpMessageConverter}s to optionally
* help decoding the response body
* @param response the HTTP response
* @param converters the message converters that may decode the HTTP response body
*/
public WebServerErrorException(ClientHttpResponse clientResponse, List<HttpMessageConverter<?>> messageConverters) {
super(clientResponse.getStatusCode().value() + " " + clientResponse.getStatusCode().getReasonPhrase(),
clientResponse, messageConverters);
public WebServerErrorException(ClientHttpResponse response, List<HttpMessageConverter<?>> converters) {
super(initMessage(response), response, converters);
}
private static String initMessage(ClientHttpResponse response) {
return response.getStatusCode().value() + " " + response.getStatusCode().getReasonPhrase();
}
}
......@@ -30,6 +30,8 @@ import reactor.core.publisher.Mono;
import org.springframework.util.Assert;
/**
* Default implementation of {@link org.springframework.web.server.WebSession}.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册