This is the multi-page printable view of this section. Click here to print.
Codec
RestClient
会自动根据用户的 Headers
与 Entity
自动选择合适的Decoder
或Encoder
进行Decode
或Encode
。同时RestClient
也支持用户在codec
前后进行插入业务逻辑。1 - Encoder
RestClient
会自动根据用户的 Headers
与 Entity
等选择合适的Encoder
进行Encode
。其内置了下面这些Encoder
:
-
Json
-
jackson :默认,自动通过SPI的方式注入到RestClient中
-
fastjson :需要引入
fastjson
依赖,并将FastJsonCodec
添加到RestClient中 -
gson :需要引入
gson
依赖,并将GsonCodec
添加到RestClient中
-
-
ProtoBuf :需要引入
ProtoBuf
依赖,并将ProtoBufCodec
添加到RestClient中 -
File :自动通过SPI的方式注入到RestClient中
-
String :自动通过SPI的方式注入到RestClient中
-
byte[] :自动通过SPI的方式注入到RestClient中
除此之外RestClient
也支持用户自定义Encoder
。
使用Json Encoder
指定contentType
为MediaType.APPLICATION_JSON
,将自动使用Json Encoder
来对Entity
来进行Encode
。示例如下:
final RestClient client = RestClient.ofDefault();
RestResponseBase response = client.post("localhost:8080/aaa")
.contentType(MediaType.APPLICATION_JSON)
.entity(new Person("Bob","male"))
.execute()
.toCompletableFuture()
.get();
Note
其中Json相关的序列化方式默认配置了日期格式为yyyy-MM-dd HH:mm:ss
使用ProtoBuf Encoder
Step1 : 引入ProtoBuf依赖
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
Step2 : 使用 ProtoBuf Encoder 进行编码
将ProtoBufCodec加入到RestClient中,指定contentType
为ProtoBufCodec.PROTO_BUF
,且Entity
类型为com.google.protobuf.Message
的子类时,将自动使用ProtoBuf Encoder
来对Entity
来进行Encode
。示例如下:
//将ProtoBufCodec加入到RestClient中
final RestClient client = RestClient.create()
.addEncoder(new ProtoBufCodec())
.build();
RestResponseBase response = client.post("localhost:8080/aaa")
.contentType(ProtoBufCodec.PROTO_BUF)
.entity(message)
.execute()
.toCompletableFuture()
.get();
使用File Encoder
当Entity
类型为File
时,将自动使用File Encoder
来对Entity
来进行Encode
。示例如下:
final RestClient client = RestClient.ofDefault();
RestResponseBase response = client.post("localhost:8080/aaa")
.entity(new File("tem"))
.execute()
.toCompletableFuture()
.get();
使用String Encoder
当Entity
类型为String
时,将自动使用String Encoder
来对Entity
来进行Encode
。示例如下:
final RestClient client = RestClient.ofDefault();
RestResponseBase response = client.post("localhost:8080/aaa")
.entity("string")
.execute()
.toCompletableFuture()
.get();
使用byte[] Encoder
当Entity
类型为byte[]
时,将自动使用byte[] Encoder
来对Entity
来进行Encode
。示例如下:
final RestClient client = RestClient.ofDefault();
RestResponseBase response = client.post("localhost:8080/aaa")
.entity("bytes".getBytes())
.execute()
.toCompletableFuture()
.get();
自定义Encoder
当RestClient
内置的Encoder
无法满足用户需求时,用户可以自定义Encoder
,示例如下:
public class StringEncoder implements ByteEncoder {
@Override
public RequestContent<byte[]> doEncode(EncodeContext<byte[]> ctx) {
if (MediaType.TEXT_PLAIN.isCompatibleWith(ctx.contentType())) {
if (ctx.entity() != null) {
return RequestContent.of(ctx.entity().toString());
} else {
return RequestContent.of("null");
}
}
//该Encoder无法Encode这种类型,将Encode工作交给下一个Encoder
return ctx.next();
}
}
Tip
在RestClient
中,同时存在多个Encoder
,它们之间通过getOrder()
方法返回值区分执行顺序,值越小,优先级越高。
针对当前Encoder
,分为两种情况:
- 当前
Encoder
可以Encode
该请求: 直接返回Encode
后的结果。 - 当前
Encoder
不可以Encode
该请求: 调用ctx.next()
,将Encode
工作交给下一个Encoder
,如果RestClient
中的所有Encoder
都无法编码该请求,则RestClient
将抛出CodecException
异常。
配置Encoder
Builder
在构造RestClient
时传入自定义的Encoder
实例,如:
final RestClient client = RestClient.create()
.addEncoder(ctx -> {
//encode...
return ctx.next();
})
.build();
SPI
普通SPI
RestClient
支持通过SPI的方式加载Encoder
接口的实现类,使用时只需要按照SPI的加载规则将自定义的Encoder
放入指定的目录下即可。
EncoderFactory
如果用户自定义的Encoder
对于不同RestClient
的配置有不同的实现,则用户可以实现EncoderFactory
接口,并按照SPI的加载规则将自定义的EncoderFactory
放入指定的目录下即可。
public interface EncoderFactory {
Collection<Encoder> encoders(RestClientOptions clientOptions);
}
在RestClient
构建时将调用EncoderFactory.encoders(RestClientOptions clientOptions)
,该方法返回的所有Encoder
都将加入到构建好的RestClient
中。
直接绑定Request
Encoder
可以直接绑定Request
,使用方式如下:
final RestResponseBase response = client.post(url)
.entity(new File("aaa"))
.encoder(ctx -> {
//encode...
return ctx.next();
})
.execute()
.toCompletableFuture()
.get();
Tip
当Request
绑定了Encoder
,该Client中设置的所有Encoder
将对该请求失效。即:如果当前Encoder
无法Encode
该请求的Entity,则RestClient
将会抛出CodecException异常。
执行时机
见请求处理完整流程中的Encoder
。
EncodeAdvice
用户可以通过EncodeAdvice
在Encode
前后插入业务逻辑,来对要Encode
的 Entity
或者 Encode
后的RequestContent
进行修改替换等操作。
示例
public class EncodeAdviceImpl implements EncodeAdvice {
@Override
public RequestContent<?> aroundEncode(EncodeAdviceContext ctx) throws Exception {
//...before encode
RequestContent<?> requestContent = ctx.next();
//...after encode
return requestContent;
}
}
Tip
多个EncodeAdvice之间通过getOrder()
方法返回值区分执行顺序,值越小,优先级越高。
配置方式
Builder
在构造RestClient
时传入自定义的EncodeAdvice
实例,如:
final RestClient client = RestClient.create()
.addEncodeAdvice(ctx -> {
//...before encode
RequestContent<?> requestContent = ctx.next();
//...after encode
return requestContent;
})
.build();
SPI
普通SPI
RestClient
支持通过SPI的方式加载EncodeAdvice
接口的实现类,使用时只需要按照SPI的加载规则将自定义的EncodeAdvice
放入指定的目录下即可。
EncodeAdviceFactory
如果用户自定义的EncodeAdvice
对于不同RestClient
的配置有不同的实现,则用户可以实现EncodeAdviceFactory
接口,并按照SPI的加载规则将自定义的EncodeAdviceFactory
放入指定的目录下即可。
public interface EncodeAdviceFactory {
Collection<EncodeAdvice> encodeAdvices(RestClientOptions clientOptions);
}
在RestClient
构建时将调用EncodeAdviceFactory.encodeAdvices(RestClientOptions clientOptions)
,该方法返回的所有EncodeAdvice
都将加入到构建好的RestClient
中。
执行时机
见请求处理完整流程中的EncodeAdvice
。
2 - Decoder
RestClient
会自动根据用户的 Headers
与 期望Entity
类型 等选择合适的Decoder
进行解码。RestClient
内置了下面这些Decoder
:
-
Json
-
jackson :默认,自动通过SPI的方式注入到RestClient中
-
fastjson :需要引入
fastjson
依赖,并将FastJsonCodec
添加到RestClient中 -
gson :需要引入
gson
依赖,并将GsonCodec
添加到RestClient中
-
-
ProtoBuf :需要引入
ProtoBuf
依赖,并将ProtoBufCodec
添加到RestClient中 -
String :自动通过SPI的方式注入到RestClient中
-
byte[] :自动通过SPI的方式注入到RestClient中
除此之外RestClient
也支持用户自定义解码器。
使用Json Decoder
当Response的contentType
为MediaType.APPLICATION_JSON
,将自动使用Json Decoder
来来进行Decode
。
final RestClient client = RestClient.ofDefault();
RestResponseBase response = client.get("localhost:8080/aaa")
.execute()
.toCompletableFuture()
.get();
//当 response.contentType() == MediaType.APPLICATION_JSON 时将自动使用Json Decoder
Person person = response.bodyToEntity(Person.class);
Note
其中Json相关的序列化方式默认配置了日期格式为yyyy-MM-dd HH:mm:ss
使用ProtoBuf Decoder
Step1 : 引入ProtoBuf依赖
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
</dependency>
Step2 : 使用 ProtoBuf Decoder 进行解码
将ProtoBufCodec加入到RestClient中, 当Response的contentType
为ProtoBufCodec.PROTO_BUF
,且response.bodyToEntity()
传入的类型为com.google.protobuf.Message
的子类时,将自动使用ProtoBuf Decoder
来进行Decode
。
//将ProtoBufCodec加入到RestClient中
final RestClient client = RestClient.create()
.addDecoder(new ProtoBufCodec())
.build();
RestResponseBase response = client.get("localhost:8080/aaa")
.execute()
.toCompletableFuture()
.get();
//当 ProtoBufCodec.PROTO_BUF.isCompatibleWith(response.contentType()),且 Person 为 Message 的子类时,将自动使用ProtoBuf Decoder
Person person = response.bodyToEntity(Person.class);
使用String Encoder
当response.bodyToEntity()
传入的类型为String.class
,且Response的contentType
不为MediaType.APPLICATION_JSON
时,将自动使用String Decoder
来进行Decode
。
final RestClient client = RestClient.ofDefault();
RestResponseBase response = client.get("localhost:8080/aaa")
.execute()
.toCompletableFuture()
.get();
//当 !MediaType.APPLICATION_JSON.isCompatibleWith(response.contentType()) 时,自动使用String Decoder来进行Decode
String result = response.bodyToEntity(String.class);
使用byte[] Encoder
当response.bodyToEntity()
传入的类型为byte[].class
,且Response的contentType
不为MediaType.APPLICATION_JSON
时,将自动使用byte[] Decoder
来进行Decode
。
final RestClient client = RestClient.ofDefault();
RestResponseBase response = client.get("localhost:8080/aaa")
.execute()
.toCompletableFuture()
.get();
//当 !MediaType.APPLICATION_JSON.isCompatibleWith(response.contentType()) 时,自动使用byte[] Decoder来进行Decode
byte[] result = response.bodyToEntity(byte[].class);
自定义Decoder
当RestClient
内置的Decoder
无法满足用户需求时,用户可以自定义Decoder
,示例如下:
public class StringDecoder implements ByteDecoder {
@Override
public Object doDecode(DecodeContext<byte[]> ctx) {
if (String.class.isAssignableFrom(ctx.targetType())) {
return new String(ctx.content().value());
}
return ctx.next();
}
}
Tip
在RestClient
中,同时存在多个Decoder
,它们之间通过getOrder()
方法返回值区分执行顺序,值越小,优先级越高。
针对当前Decoder
,分为两种情况:
- 当前
Decoder
可以Decode
该响应: 直接返回Decode
后的结果。 - 当前
Decoder
不可以Decode
该响应: 调用ctx.next()
,将Decode
工作交给下一个Decoder
,如果RestClient
中的所有Decoder
都无法编码该请求,则RestClient
将抛出CodecException
异常。
配置Decoder
Builder
在构造RestClient
时传入自定义的Decoder
实例,如:
final RestClient client = RestClient.create()
.addDecoder(ctx -> {
//decode...
return ctx.next();
})
.build();
SPI
普通SPI
RestClient
支持通过SPI的方式加载Decoder
接口的实现类,使用时只需要按照SPI的加载规则将自定义的Decoder
放入指定的目录下即可。
DecoderFactory
如果用户自定义的Decoder
对于不同RestClient
的配置有不同的实现,则用户可以实现DecoderFactory
接口,并按照SPI的加载规则将自定义的DecoderFactory
放入指定的目录下即可。
public interface DecoderFactory {
Collection<Decoder> decoders(RestClientOptions clientOptions);
}
在RestClient
构建时将调用DecoderFactory.decoders(RestClientOptions clientOptions)
,该方法返回的所有Decoder
都将加入到构建好的RestClient
中。
直接绑定Request
Decoder
可以直接绑定Request
,使用方式如下:
final RestResponseBase response = client.post(url)
.entity(new File("aaa"))
.decoder(ctx -> {
//decode...
return ctx.next();
})
.execute()
.toCompletableFuture()
.get();
Tip
当Request
绑定了Decoder
,该Client中设置的所有Decoder
将对该请求失效。即:如果当前Decoder
无法解码该响应,则RestClient
将会抛出CodecException异常。
执行时机
见请求处理完整流程中的Decoder
。
DecodeAdvice
用户可以通过DecodeAdvice
在Decode
前后进行来插入业务逻辑,来对要解码的 ResponseContent
或者 Decode
后的对象 进行修改替换等操作。
示例
public class DecodeAdviceImpl implements DecodeAdvice {
@Override
public Object aroundDecode(DecodeAdviceContext ctx) throws Exception {
//...before decode
Object decoded = ctx.next();
//...after decode
return decoded;
}
}
Tip
多个DecodeAdvice
之间通过getOrder()
方法返回值区分执行顺序,值越小,优先级越高。
配置方式
Builder
在构造RestClient
时传入自定义的DecodeAdvice
实例,如:
final RestClient client = RestClient.create()
.addDecodeAdvice(ctx ->{
//...before decode
Object decoded = ctx.next();
//...after decode
return decoded;
})
.build();
SPI
普通SPI
RestClient
支持通过SPI的方式加载DecodeAdvice
接口的实现类,使用时只需要按照SPI的加载规则将自定义的DecodeAdvice
放入指定的目录下即可。
DecodeAdviceFactory
如果用户自定义的DecodeAdvice
对于不同RestClient
的配置有不同的实现,则用户可以实现DecodeAdviceFactory
接口,并按照SPI的加载规则将自定义的DecodeAdviceFactory
放入指定的目录下即可。
public interface DecodeAdviceFactory {
Collection<DecodeAdvice> decodeAdvices(RestClientOptions clientOptions);
}
在RestClient
构建时将调用DecodeAdviceFactory.decodeAdvices(RestClientOptions clientOptions)
,该方法返回的所有DecodeAdvice
都将加入到构建好的RestClient
中。
执行时机
见请求处理完整流程中的DecodeAdvice
。