Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
e4d40527
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e4d40527
编写于
11月 03, 2017
作者:
A
Arjen Poutsma
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Document DataBuffer/PooledDataBuffer and codecs
Issue: SPR-16156
上级
cc7c90cc
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
165 addition
and
10 deletion
+165
-10
spring-core/src/main/java/org/springframework/core/io/buffer/DataBuffer.java
...n/java/org/springframework/core/io/buffer/DataBuffer.java
+5
-5
spring-core/src/main/java/org/springframework/core/io/buffer/DataBufferFactory.java
...org/springframework/core/io/buffer/DataBufferFactory.java
+6
-4
src/docs/asciidoc/core.adoc
src/docs/asciidoc/core.adoc
+2
-0
src/docs/asciidoc/core/core-databuffer-codec.adoc
src/docs/asciidoc/core/core-databuffer-codec.adoc
+150
-0
src/docs/asciidoc/web/webflux.adoc
src/docs/asciidoc/web/webflux.adoc
+2
-1
未找到文件。
spring-core/src/main/java/org/springframework/core/io/buffer/DataBuffer.java
浏览文件 @
e4d40527
...
...
@@ -40,9 +40,9 @@ import java.util.function.IntPredicate;
* <p>The {@linkplain #capacity() capacity} of a {@code DataBuffer} is expanded on demand,
* similar to {@code StringBuilder}.
*
* <p>The main purpose of the {@code DataBuffer} abstraction is
provide a convenient wrapper around
*
{@link ByteBuffer}, similar to Netty's {@link io.netty.buffer.ByteBuf}, that can also be used on
* non-Netty platforms (i.e. Servlet).
* <p>The main purpose of the {@code DataBuffer} abstraction is
to provide a convenient wrapper
*
around {@link ByteBuffer} that is similar to Netty's {@link io.netty.buffer.ByteBuf}, but that
*
can also be used on
non-Netty platforms (i.e. Servlet).
*
* @author Arjen Poutsma
* @since 5.0
...
...
@@ -237,14 +237,14 @@ public interface DataBuffer {
ByteBuffer
asByteBuffer
(
int
index
,
int
length
);
/**
* Expose this buffer's data as an {@link InputStream}. Both data and position are
* Expose this buffer's data as an {@link InputStream}. Both data and
read
position are
* shared between the returned stream and this data buffer.
* @return this data buffer as an input stream
*/
InputStream
asInputStream
();
/**
* Expose this buffer's data as an {@link OutputStream}. Both data and position are
* Expose this buffer's data as an {@link OutputStream}. Both data and
write
position are
* shared between the returned stream and this data buffer.
* @return this data buffer as an output stream
*/
...
...
spring-core/src/main/java/org/springframework/core/io/buffer/DataBufferFactory.java
浏览文件 @
e4d40527
/*
* Copyright 2002-201
6
the original author or authors.
* Copyright 2002-201
7
the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -19,7 +19,7 @@ package org.springframework.core.io.buffer;
import
java.nio.ByteBuffer
;
/**
* A factory for {@link DataBuffer}s,allowing for allocation and wrapping of
* A factory for {@link DataBuffer}s,
allowing for allocation and wrapping of
* data buffers.
*
* @author Arjen Poutsma
...
...
@@ -46,14 +46,16 @@ public interface DataBufferFactory {
DataBuffer
allocateBuffer
(
int
initialCapacity
);
/**
* Wrap the given {@link ByteBuffer} in a {@code DataBuffer}.
* Wrap the given {@link ByteBuffer} in a {@code DataBuffer}. Unlike
* {@linkplain #allocateBuffer(int) allocating}, wrapping does not use new memory.
* @param byteBuffer the NIO byte buffer to wrap
* @return the wrapped buffer
*/
DataBuffer
wrap
(
ByteBuffer
byteBuffer
);
/**
* Wrap the given {@code byte} array in a {@code DataBuffer}.
* Wrap the given {@code byte} array in a {@code DataBuffer}. Unlike
* {@linkplain #allocateBuffer(int) allocating}, wrapping does not use new memory.
* @param bytes the byte array to wrap
* @return the wrapped buffer
*/
...
...
src/docs/asciidoc/core.adoc
浏览文件 @
e4d40527
...
...
@@ -34,4 +34,6 @@ include::core/core-aop-api.adoc[leveloffset=+1]
include::core/core-null-safety.adoc[leveloffset=+1]
include::core/core-databuffer-codec.adoc[leveloffset=+1]
include::core/core-appendix.adoc[leveloffset=+1]
src/docs/asciidoc/core/core-databuffer-codec.adoc
0 → 100644
浏览文件 @
e4d40527
[[databuffers]]
= Data Buffers and Codecs
== Introduction
The `DataBuffer` interface defines an abstraction over byte buffers.
The main reason for introducing it, and not use the standard `java.nio.ByteBuffer` instead, is Netty.
Netty does not use `ByteBuffer`, but instead offers `ByteBuf` as an alternative.
Spring's `DataBuffer` is a simple abstraction over `ByteBuf` that can also be used on non-Netty
platforms (i.e. Servlet 3.1+).
== `DataBufferFactory`
The `DataBufferFactory` offers functionality to allocate new data buffers, as well as to wrap
existing data.
The `allocate` methods allocate a new data buffer, with a default or given capacity.
Though `DataBuffer` implementation grow and shrink on demand, it is more efficient to give the
capacity upfront, if known.
The `wrap` methods decorate an existing `ByteBuffer` or byte array.
Wrapping does not involve allocation: it simply decorates the given data with a `DataBuffer`
implementation.
There are two implementation of `DataBufferFactory`: the `NettyDataBufferFactory` which is meant
to be used on Netty platforms, such as Reactor Netty.
The other implementation, the `DefaultDataBufferFactory`, is used on other platforms, such as
Servlet 3.1+ servers.
== The `DataBuffer` interface
The `DataBuffer` interface is similar to `ByteBuffer`, but offers a number of advantages.
Similar to Netty's `ByteBuf`, the `DataBuffer` abstraction offers independent read and write
positions.
This is different from the JDK's `ByteBuffer`, which only exposes one position for both reading and
writing, and a separate `flip()` operation to switch between the two I/O operations.
In general, the following invariant holds for the read position, write position, and the capacity:
--
`0` <= _read position_ <= _write position_ <= _capacity_
--
When reading bytes from the `DataBuffer`, the read position is automatically updated in accordance with
the amount of data read from the buffer.
Similarly, when writing bytes to the `DataBuffer`, the write position is updated with the amount of
data written to the buffer.
Also, when writing data, the capacity of a `DataBuffer` is automatically expanded, just like `StringBuilder`,
`ArrayList`, and similar types.
Besides the reading and writing functionality mentioned above, the `DataBuffer` also has methods to
view a (slice of a) buffer as `ByteBuffer`, `InputStream`, or `OutputStream`.
Additionally, it offers methods to determine the index of a given byte.
There are two implementation of `DataBuffer`: the `NettyDataBuffer` which is meant to be used on
Netty platforms, such as Reactor Netty.
The other implementation, the `DefaultDataBuffer`, is used on other platforms, such as Servlet 3.1+
servers.
=== `PooledDataBuffer`
The `PooledDataBuffer` is an extension to `DataBuffer` that adds methods for reference counting.
The `retain` method increases the reference count by one.
The `release` method decreases the count by one, and releases the buffer's memory when the count
reaches 0.
Both of these methods are related to _reference counting_, a mechanism that is explained below.
Note that `DataBufferUtils` offers useful utility methods for releasing and retaining pooled data
buffers.
These methods take a plain `DataBuffer` as parameter, but only call `retain` or `release` if the
passed data buffer is an instance of `PooledDataBuffer`.
[[databuffer-reference-counting]]
==== Reference Counting
Reference counting is not a common technique in Java; it is much more common in other programming
languages such as Object C and C++.
In and of itself, reference counting is not complex: it basically involves tracking the number of
references that apply to an object.
The reference count of a `PooledDataBuffer` starts at 1, is incremented by calling `retain`,
and decremented by calling `release`.
As long as the buffer's reference count is larger than 0 the buffer will not be released.
When the number decreases to 0, the instance will be released.
In practice, this means that the reserved memory captured by the buffer will be returned back to
the memory pool, ready to be used for future allocations.
In general, _the last component to access a `DataBuffer` is responsible for releasing it_.
Withing Spring, there are two sorts of components that release buffers: decoders and transports.
Decoders are responsible for transforming a stream of buffers into other types (see <<codecs>> below),
and transports are responsible for sending buffers across a network boundary, typically as an HTTP message.
This means that if you allocate data buffers for the purpose of putting them into an outbound HTTP
message (i.e. client-side request or server-side response), they do not have to be released.
The other consequence of this rule is that if you allocate data buffers that do not end up in the
body, for instance because of a thrown exception, you will have to release them yourself.
The following snippet shows a typical `DataBuffer` usage scenario when dealing with methods that
throw exceptions:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
DataBufferFactory factory = ...
DataBuffer buffer = factory.allocateBuffer(); <1>
boolean release = true; <2>
try {
writeDataToBuffer(buffer); <3>
putBufferInHttpBody(buffer);
release = false; <4>
} finally {
if (release) {
DataBufferUtils.release(buffer); <5>
}
}
private void writeDataToBuffer(DataBuffer buffer) throws IOException { <3>
...
}
----
<1> A new buffer is allocated.
<2> A boolean flag indicates whether the allocated buffer should be released.
<3> This example method loads data into the buffer. Note that the method can throw an `IOException`,
and therefore a `finally` block to release the buffer is required.
<4> If no exception occurred, we switch the `release` flag to `false` as the buffer will now be
released as part of sending the HTTP body across the wire.
<5> If an exception did occur, the flag is still set to `true`, and the buffer will be released
here.
=== DataBufferUtils
`DataBufferUtils` contains various utility methods that operate on data buffers.
It contains methods for reading a `Flux` of `DataBuffer` objects from an `InputStream` or NIO
`Channel`, and methods for writing a data buffer `Flux` to an `OutputStream` or `Channel`.
`DataBufferUtils` also exposes `retain` and `release` methods that operate on plain `DataBuffer`
instances (so that casting to a `PooledDataBuffer` is not required).
[codecs]
== Codecs
The `org.springframework.core.codec` package contains the two main abstractions for converting a
stream of bytes into a stream of objects, or vice-versa.
The `Encoder` is a strategy interface that encodes a stream of objects into an output stream of
data buffers.
The `Decoder` does the reverse: it turns a stream of data buffers into a stream of objects.
Note that a decoder instance needs to consider <<databuffer-reference-counting, reference counting>>.
Spring comes with a wide array of default codecs, capable of converting from/to `String`,
`ByteBuffer`, byte arrays, and also codecs that support marshalling libraries such as JAXB and
Jackson.
Withing the context of Spring WebFlux, codecs are used to convert the request body into a
`@RequestMapping` parameter, or to convert the return type into the response body that is sent back
to the client.
The default codecs are configured in the `WebFluxConfigurationSupport` class, and can easily be
changed by overriding the `configureHttpMessageCodecs` when inheriting from that class.
For more information about using codecs in WebFlux, see <<web-reactive#webflux-codecs, this section>>.
src/docs/asciidoc/web/webflux.adoc
浏览文件 @
e4d40527
...
...
@@ -434,7 +434,8 @@ for encoding and decoding the HTTP request and response body with Reactive Strea
It builds on lower level contracts from `spring-core`:
* {api-spring-framework}/core/io/buffer/DataBuffer.html[DataBuffer] -- abstraction for
byte buffers -- e.g. Netty `ByteBuf`, `java.nio.ByteBuffer`
byte buffers -- e.g. Netty `ByteBuf`, `java.nio.ByteBuffer`, see
<<core#databuffers, Data Buffers and Codecs>>.
* {api-spring-framework}/core/codec/Encoder.html[Encoder] -- serialize a stream of Objects
to a stream of data buffers
* {api-spring-framework}/core/codec/Decoder.html[Decoder] -- deserialize a stream of data
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录