下面列出了怎么用org.springframework.core.codec.Encoder的API类实例代码及写法,或者点击链接到github查看源代码。
private MessageMappingMessageHandler initMesssageHandler() {
List<Decoder<?>> decoders = Collections.singletonList(StringDecoder.allMimeTypes());
List<Encoder<?>> encoders = Collections.singletonList(CharSequenceEncoder.allMimeTypes());
ReactiveAdapterRegistry registry = ReactiveAdapterRegistry.getSharedInstance();
this.returnValueHandler = new TestEncoderMethodReturnValueHandler(encoders, registry);
PropertySource<?> source = new MapPropertySource("test", Collections.singletonMap("path", "path123"));
StaticApplicationContext context = new StaticApplicationContext();
context.getEnvironment().getPropertySources().addFirst(source);
context.registerSingleton("testController", TestController.class);
context.refresh();
MessageMappingMessageHandler messageHandler = new MessageMappingMessageHandler();
messageHandler.getReturnValueHandlerConfigurer().addCustomHandler(this.returnValueHandler);
messageHandler.setApplicationContext(context);
messageHandler.setEmbeddedValueResolver(new EmbeddedValueResolver(context.getBeanFactory()));
messageHandler.setDecoders(decoders);
messageHandler.afterPropertiesSet();
return messageHandler;
}
@SuppressWarnings("unchecked")
private <T> List<DataBuffer> encodeEvent(CharSequence markup, @Nullable T data, ResolvableType dataType,
MediaType mediaType, DataBufferFactory factory, Map<String, Object> hints) {
List<DataBuffer> result = new ArrayList<>(4);
result.add(encodeText(markup, mediaType, factory));
if (data != null) {
if (data instanceof String) {
String dataLine = StringUtils.replace((String) data, "\n", "\ndata:") + "\n";
result.add(encodeText(dataLine, mediaType, factory));
}
else if (this.encoder == null) {
throw new CodecException("No SSE encoder configured and the data is not String.");
}
else {
result.add(((Encoder<T>) this.encoder).encodeValue(data, factory, dataType, mediaType, hints));
result.add(encodeText("\n", mediaType, factory));
}
}
result.add(encodeText("\n", mediaType, factory));
return result;
}
/**
* Return writers that support specific types.
* @param forMultipart whether to returns writers for general use ("false"),
* or for multipart requests only ("true"). Generally the two sets are the
* same except for the multipart writer itself.
*/
@SuppressWarnings("unchecked")
final List<HttpMessageWriter<?>> getTypedWriters(boolean forMultipart) {
if (!this.registerDefaults) {
return Collections.emptyList();
}
List<HttpMessageWriter<?>> writers = new ArrayList<>();
writers.add(new EncoderHttpMessageWriter<>(new ByteArrayEncoder()));
writers.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
writers.add(new EncoderHttpMessageWriter<>(new DataBufferEncoder()));
writers.add(new ResourceHttpMessageWriter());
writers.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly()));
// No client or server specific multipart writers currently..
if (!forMultipart) {
extendTypedWriters(writers);
}
if (protobufPresent) {
Encoder<?> encoder = this.protobufEncoder != null ? this.protobufEncoder : new ProtobufEncoder();
writers.add(new ProtobufHttpMessageWriter((Encoder) encoder));
}
return writers;
}
/**
* Return Object writers (JSON, XML, SSE).
* @param forMultipart whether to returns writers for general use ("false"),
* or for multipart requests only ("true"). Generally the two sets are the
* same except for the multipart writer itself.
*/
final List<HttpMessageWriter<?>> getObjectWriters(boolean forMultipart) {
if (!this.registerDefaults) {
return Collections.emptyList();
}
List<HttpMessageWriter<?>> writers = new ArrayList<>();
if (jackson2Present) {
writers.add(new EncoderHttpMessageWriter<>(getJackson2JsonEncoder()));
}
if (jackson2SmilePresent) {
writers.add(new EncoderHttpMessageWriter<>(new Jackson2SmileEncoder()));
}
if (jaxb2Present) {
Encoder<?> encoder = this.jaxb2Encoder != null ? this.jaxb2Encoder : new Jaxb2XmlEncoder();
writers.add(new EncoderHttpMessageWriter<>(encoder));
}
// No client or server specific multipart writers currently..
if (!forMultipart) {
extendObjectWriters(writers);
}
return writers;
}
@SuppressWarnings("unchecked")
private <T> Flux<DataBuffer> encodeData(@Nullable T data, ResolvableType valueType,
MediaType mediaType, DataBufferFactory factory, Map<String, Object> hints) {
if (data == null) {
return Flux.empty();
}
if (data instanceof String) {
String text = (String) data;
return Flux.from(encodeText(StringUtils.replace(text, "\n", "\ndata:") + "\n", mediaType, factory));
}
if (this.encoder == null) {
return Flux.error(new CodecException("No SSE encoder configured and the data is not String."));
}
return ((Encoder<T>) this.encoder)
.encode(Mono.just(data), factory, valueType, mediaType, hints)
.concatWith(encodeText("\n", mediaType, factory));
}
/**
* Return writers that support specific types.
* @param forMultipart whether to returns writers for general use ("false"),
* or for multipart requests only ("true"). Generally the two sets are the
* same except for the multipart writer itself.
*/
@SuppressWarnings("unchecked")
final List<HttpMessageWriter<?>> getTypedWriters(boolean forMultipart) {
if (!this.registerDefaults) {
return Collections.emptyList();
}
List<HttpMessageWriter<?>> writers = new ArrayList<>();
writers.add(new EncoderHttpMessageWriter<>(new ByteArrayEncoder()));
writers.add(new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
writers.add(new EncoderHttpMessageWriter<>(new DataBufferEncoder()));
writers.add(new ResourceHttpMessageWriter());
writers.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly()));
// No client or server specific multipart writers currently..
if (!forMultipart) {
extendTypedWriters(writers);
}
if (protobufPresent) {
Encoder<?> encoder = this.protobufEncoder != null ? this.protobufEncoder : new ProtobufEncoder();
writers.add(new ProtobufHttpMessageWriter((Encoder) encoder));
}
return writers;
}
/**
* Return Object writers (JSON, XML, SSE).
* @param forMultipart whether to returns writers for general use ("false"),
* or for multipart requests only ("true"). Generally the two sets are the
* same except for the multipart writer itself.
*/
final List<HttpMessageWriter<?>> getObjectWriters(boolean forMultipart) {
if (!this.registerDefaults) {
return Collections.emptyList();
}
List<HttpMessageWriter<?>> writers = new ArrayList<>();
if (jackson2Present) {
writers.add(new EncoderHttpMessageWriter<>(getJackson2JsonEncoder()));
}
if (jackson2SmilePresent) {
writers.add(new EncoderHttpMessageWriter<>(new Jackson2SmileEncoder()));
}
if (jaxb2Present) {
Encoder<?> encoder = this.jaxb2Encoder != null ? this.jaxb2Encoder : new Jaxb2XmlEncoder();
writers.add(new EncoderHttpMessageWriter<>(encoder));
}
// No client or server specific multipart writers currently..
if (!forMultipart) {
extendObjectWriters(writers);
}
return writers;
}
@SuppressWarnings("unchecked")
private Flux<DataBuffer> encodeContent(
@Nullable Object content, MethodParameter returnType, DataBufferFactory bufferFactory,
@Nullable MimeType mimeType, Map<String, Object> hints) {
ResolvableType returnValueType = ResolvableType.forMethodParameter(returnType);
ReactiveAdapter adapter = getAdapterRegistry().getAdapter(returnValueType.resolve(), content);
Publisher<?> publisher;
ResolvableType elementType;
if (adapter != null) {
publisher = adapter.toPublisher(content);
boolean isUnwrapped = KotlinDetector.isKotlinReflectPresent() &&
KotlinDetector.isKotlinType(returnType.getContainingClass()) &&
KotlinDelegate.isSuspend(returnType.getMethod()) &&
!COROUTINES_FLOW_CLASS_NAME.equals(returnValueType.toClass().getName());
ResolvableType genericType = isUnwrapped ? returnValueType : returnValueType.getGeneric();
elementType = getElementType(adapter, genericType);
}
else {
publisher = Mono.justOrEmpty(content);
elementType = (returnValueType.toClass() == Object.class && content != null ?
ResolvableType.forInstance(content) : returnValueType);
}
if (elementType.resolve() == void.class || elementType.resolve() == Void.class) {
return Flux.from(publisher).cast(DataBuffer.class);
}
Encoder<?> encoder = getEncoder(elementType, mimeType);
return Flux.from((Publisher) publisher).map(value ->
encodeValue(value, elementType, encoder, bufferFactory, mimeType, hints));
}
@Nullable
@SuppressWarnings("unchecked")
private <T> Encoder<T> getEncoder(ResolvableType elementType, @Nullable MimeType mimeType) {
for (Encoder<?> encoder : getEncoders()) {
if (encoder.canEncode(elementType, mimeType)) {
return (Encoder<T>) encoder;
}
}
return null;
}
@SuppressWarnings("unchecked")
private <T> DataBuffer encodeValue(
Object element, ResolvableType elementType, @Nullable Encoder<T> encoder,
DataBufferFactory bufferFactory, @Nullable MimeType mimeType,
@Nullable Map<String, Object> hints) {
if (encoder == null) {
encoder = getEncoder(ResolvableType.forInstance(element), mimeType);
if (encoder == null) {
throw new MessagingException(
"No encoder for " + elementType + ", current value type is " + element.getClass());
}
}
return encoder.encodeValue((T) element, bufferFactory, elementType, mimeType, hints);
}
/**
* Return the {@code RSocketStrategies} instance provided via
* {@link #setRSocketStrategies rsocketStrategies}, or
* otherwise initialize it with the configured {@link #setEncoders(List)
* encoders}, {@link #setDecoders(List) decoders}, and others.
*/
public RSocketStrategies getRSocketStrategies() {
if (this.rsocketStrategies == null) {
this.rsocketStrategies = RSocketStrategies.builder()
.decoder(getDecoders().toArray(new Decoder<?>[0]))
.encoder(getEncoders().toArray(new Encoder<?>[0]))
.reactiveAdapterStrategy(getReactiveAdapterRegistry())
.build();
}
return this.rsocketStrategies;
}
private DefaultRSocketStrategies(List<Encoder<?>> encoders, List<Decoder<?>> decoders,
ReactiveAdapterRegistry adapterRegistry, DataBufferFactory bufferFactory) {
this.encoders = Collections.unmodifiableList(encoders);
this.decoders = Collections.unmodifiableList(decoders);
this.adapterRegistry = adapterRegistry;
this.bufferFactory = bufferFactory;
}
@SuppressWarnings("unchecked")
private <T> DataBuffer encodeValue(T value, ResolvableType valueType, @Nullable Encoder<?> encoder) {
if (encoder == null) {
encoder = strategies.encoder(ResolvableType.forInstance(value), dataMimeType);
}
return ((Encoder<T>) encoder).encodeValue(
value, strategies.dataBufferFactory(), valueType, dataMimeType, EMPTY_HINTS);
}
/**
* Create an instance wrapping the given {@link Encoder}.
*/
public EncoderHttpMessageWriter(Encoder<T> encoder) {
Assert.notNull(encoder, "Encoder is required");
initLogger(encoder);
this.encoder = encoder;
this.mediaTypes = MediaType.asMediaTypes(encoder.getEncodableMimeTypes());
this.defaultMediaType = initDefaultMediaType(this.mediaTypes);
}
private static void initLogger(Encoder<?> encoder) {
if (encoder instanceof AbstractEncoder &&
encoder.getClass().getName().startsWith("org.springframework.core.codec")) {
Log logger = HttpLogging.forLog(((AbstractEncoder) encoder).getLogger());
((AbstractEncoder) encoder).setLogger(logger);
}
}
private void assertSseWriter(List<HttpMessageWriter<?>> writers) {
HttpMessageWriter<?> writer = writers.get(this.index.getAndIncrement());
assertEquals(ServerSentEventHttpMessageWriter.class, writer.getClass());
Encoder<?> encoder = ((ServerSentEventHttpMessageWriter) writer).getEncoder();
assertNotNull(encoder);
assertEquals(Jackson2JsonEncoder.class, encoder.getClass());
}
@Test
public void defaultAndCustomWriters() {
Encoder<?> customEncoder1 = mock(Encoder.class);
Encoder<?> customEncoder2 = mock(Encoder.class);
given(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).willReturn(false);
given(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).willReturn(true);
HttpMessageWriter<?> customWriter1 = mock(HttpMessageWriter.class);
HttpMessageWriter<?> customWriter2 = mock(HttpMessageWriter.class);
given(customWriter1.canWrite(ResolvableType.forClass(Object.class), null)).willReturn(false);
given(customWriter2.canWrite(ResolvableType.forClass(Object.class), null)).willReturn(true);
this.configurer.customCodecs().encoder(customEncoder1);
this.configurer.customCodecs().encoder(customEncoder2);
this.configurer.customCodecs().writer(customWriter1);
this.configurer.customCodecs().writer(customWriter2);
List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
assertEquals(14, writers.size());
assertSame(customEncoder1, getNextEncoder(writers));
assertSame(customWriter1, writers.get(this.index.getAndIncrement()));
assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass());
assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ProtobufHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
assertSame(customEncoder2, getNextEncoder(writers));
assertSame(customWriter2, writers.get(this.index.getAndIncrement()));
assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
}
@Test
public void defaultsOffWithCustomWriters() {
Encoder<?> customEncoder1 = mock(Encoder.class);
Encoder<?> customEncoder2 = mock(Encoder.class);
given(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).willReturn(false);
given(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).willReturn(true);
HttpMessageWriter<?> customWriter1 = mock(HttpMessageWriter.class);
HttpMessageWriter<?> customWriter2 = mock(HttpMessageWriter.class);
given(customWriter1.canWrite(ResolvableType.forClass(Object.class), null)).willReturn(false);
given(customWriter2.canWrite(ResolvableType.forClass(Object.class), null)).willReturn(true);
this.configurer.customCodecs().encoder(customEncoder1);
this.configurer.customCodecs().encoder(customEncoder2);
this.configurer.customCodecs().writer(customWriter1);
this.configurer.customCodecs().writer(customWriter2);
this.configurer.registerDefaults(false);
List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
assertEquals(4, writers.size());
assertSame(customEncoder1, getNextEncoder(writers));
assertSame(customWriter1, writers.get(this.index.getAndIncrement()));
assertSame(customEncoder2, getNextEncoder(writers));
assertSame(customWriter2, writers.get(this.index.getAndIncrement()));
}
private void assertEncoderInstance(Encoder<?> encoder) {
assertSame(encoder, this.configurer.getWriters().stream()
.filter(writer -> writer instanceof EncoderHttpMessageWriter)
.map(writer -> ((EncoderHttpMessageWriter<?>) writer).getEncoder())
.filter(e -> encoder.getClass().equals(e.getClass()))
.findFirst()
.filter(e -> e == encoder).orElse(null));
}
/**
* Create an instance wrapping the given {@link Encoder}.
*/
public EncoderHttpMessageWriter(Encoder<T> encoder) {
Assert.notNull(encoder, "Encoder is required");
initLogger(encoder);
this.encoder = encoder;
this.mediaTypes = MediaType.asMediaTypes(encoder.getEncodableMimeTypes());
this.defaultMediaType = initDefaultMediaType(this.mediaTypes);
}
private static void initLogger(Encoder<?> encoder) {
if (encoder instanceof AbstractEncoder &&
encoder.getClass().getName().startsWith("org.springframework.core.codec")) {
Log logger = HttpLogging.forLog(((AbstractEncoder) encoder).getLogger());
((AbstractEncoder) encoder).setLogger(logger);
}
}
private void assertSseWriter(List<HttpMessageWriter<?>> writers) {
HttpMessageWriter<?> writer = writers.get(this.index.getAndIncrement());
assertEquals(ServerSentEventHttpMessageWriter.class, writer.getClass());
Encoder<?> encoder = ((ServerSentEventHttpMessageWriter) writer).getEncoder();
assertNotNull(encoder);
assertEquals(Jackson2JsonEncoder.class, encoder.getClass());
}
@Test
public void defaultAndCustomWriters() {
Encoder<?> customEncoder1 = mock(Encoder.class);
Encoder<?> customEncoder2 = mock(Encoder.class);
when(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
when(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
HttpMessageWriter<?> customWriter1 = mock(HttpMessageWriter.class);
HttpMessageWriter<?> customWriter2 = mock(HttpMessageWriter.class);
when(customWriter1.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(false);
when(customWriter2.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(true);
this.configurer.customCodecs().encoder(customEncoder1);
this.configurer.customCodecs().encoder(customEncoder2);
this.configurer.customCodecs().writer(customWriter1);
this.configurer.customCodecs().writer(customWriter2);
List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
assertEquals(14, writers.size());
assertEquals(ByteArrayEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ByteBufferEncoder.class, getNextEncoder(writers).getClass());
assertEquals(DataBufferEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ResourceHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
assertEquals(ProtobufHttpMessageWriter.class, writers.get(index.getAndIncrement()).getClass());
assertSame(customEncoder1, getNextEncoder(writers));
assertSame(customWriter1, writers.get(this.index.getAndIncrement()));
assertEquals(Jackson2JsonEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jackson2SmileEncoder.class, getNextEncoder(writers).getClass());
assertEquals(Jaxb2XmlEncoder.class, getNextEncoder(writers).getClass());
assertSame(customEncoder2, getNextEncoder(writers));
assertSame(customWriter2, writers.get(this.index.getAndIncrement()));
assertEquals(CharSequenceEncoder.class, getNextEncoder(writers).getClass());
}
@Test
public void defaultsOffWithCustomWriters() {
Encoder<?> customEncoder1 = mock(Encoder.class);
Encoder<?> customEncoder2 = mock(Encoder.class);
when(customEncoder1.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(false);
when(customEncoder2.canEncode(ResolvableType.forClass(Object.class), null)).thenReturn(true);
HttpMessageWriter<?> customWriter1 = mock(HttpMessageWriter.class);
HttpMessageWriter<?> customWriter2 = mock(HttpMessageWriter.class);
when(customWriter1.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(false);
when(customWriter2.canWrite(ResolvableType.forClass(Object.class), null)).thenReturn(true);
this.configurer.customCodecs().encoder(customEncoder1);
this.configurer.customCodecs().encoder(customEncoder2);
this.configurer.customCodecs().writer(customWriter1);
this.configurer.customCodecs().writer(customWriter2);
this.configurer.registerDefaults(false);
List<HttpMessageWriter<?>> writers = this.configurer.getWriters();
assertEquals(4, writers.size());
assertSame(customEncoder1, getNextEncoder(writers));
assertSame(customWriter1, writers.get(this.index.getAndIncrement()));
assertSame(customEncoder2, getNextEncoder(writers));
assertSame(customWriter2, writers.get(this.index.getAndIncrement()));
}
private void assertEncoderInstance(Encoder<?> encoder) {
assertSame(encoder, this.configurer.getWriters().stream()
.filter(writer -> writer instanceof EncoderHttpMessageWriter)
.map(writer -> ((EncoderHttpMessageWriter<?>) writer).getEncoder())
.filter(e -> encoder.getClass().equals(e.getClass()))
.findFirst()
.filter(e -> e == encoder).orElse(null));
}
@SuppressWarnings("unchecked")
private <T> DataBuffer encodeEntry(Object metadata, MimeType mimeType) {
if (metadata instanceof ByteBuf) {
return asDataBuffer((ByteBuf) metadata);
}
ResolvableType type = ResolvableType.forInstance(metadata);
Encoder<T> encoder = this.strategies.encoder(type, mimeType);
Assert.notNull(encoder, () -> "No encoder for metadata " + metadata
+ ", mimeType '" + mimeType + "'");
return encoder.encodeValue((T) metadata, bufferFactory(), type, mimeType,
Collections.emptyMap());
}
protected AbstractEncoderMethodReturnValueHandler(List<Encoder<?>> encoders, ReactiveAdapterRegistry registry) {
Assert.notEmpty(encoders, "At least one Encoder is required");
Assert.notNull(registry, "ReactiveAdapterRegistry is required");
this.encoders = Collections.unmodifiableList(encoders);
this.adapterRegistry = registry;
}
/**
* The configured encoders.
*/
public List<Encoder<?>> getEncoders() {
return this.encoders;
}
/**
* Configure the encoders to use for encoding handler method return values.
*/
public void setEncoders(List<? extends Encoder<?>> encoders) {
this.encoders.addAll(encoders);
}
/**
* Return the configured {@link #setEncoders(List) encoders}.
*/
public List<? extends Encoder<?>> getEncoders() {
return this.encoders;
}