Support to customize rather than replace default codecs
See gh-26212
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
* Copyright 2002-2021 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.
|
||||
@@ -192,6 +192,17 @@ public interface CodecConfigurer {
|
||||
*/
|
||||
void kotlinSerializationJsonEncoder(Encoder<?> encoder);
|
||||
|
||||
/**
|
||||
* Register a consumer to apply to default config instances. This can be
|
||||
* used to configure rather than replace a specific codec or multiple
|
||||
* codecs. The consumer is applied to every default {@link Encoder},
|
||||
* {@link Decoder}, {@link HttpMessageReader} and {@link HttpMessageWriter}
|
||||
* instance.
|
||||
* @param codecConsumer the consumer to apply
|
||||
* @since 5.3.4
|
||||
*/
|
||||
void configureDefaultCodec(Consumer<Object> codecConsumer);
|
||||
|
||||
/**
|
||||
* Configure a limit on the number of bytes that can be buffered whenever
|
||||
* the input stream needs to be aggregated. This can be a result of
|
||||
|
||||
@@ -84,7 +84,7 @@ public abstract class Jackson2CodecSupport {
|
||||
|
||||
protected final Log logger = HttpLogging.forLogName(getClass());
|
||||
|
||||
private final ObjectMapper defaultObjectMapper;
|
||||
private ObjectMapper defaultObjectMapper;
|
||||
|
||||
@Nullable
|
||||
private Map<Class<?>, Map<MimeType, ObjectMapper>> objectMapperRegistrations;
|
||||
@@ -103,6 +103,19 @@ public abstract class Jackson2CodecSupport {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure the default ObjectMapper instance to use.
|
||||
* @param objectMapper the ObjectMapper instance
|
||||
* @since 5.3.4
|
||||
*/
|
||||
public void setObjectMapper(ObjectMapper objectMapper) {
|
||||
Assert.notNull(objectMapper, "ObjectMapper must not be null");
|
||||
this.defaultObjectMapper = objectMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link #setObjectMapper configured} default ObjectMapper.
|
||||
*/
|
||||
public ObjectMapper getObjectMapper() {
|
||||
return this.defaultObjectMapper;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.springframework.core.SpringProperties;
|
||||
import org.springframework.core.codec.AbstractDataBufferDecoder;
|
||||
@@ -46,6 +47,7 @@ import org.springframework.http.codec.HttpMessageWriter;
|
||||
import org.springframework.http.codec.ResourceHttpMessageReader;
|
||||
import org.springframework.http.codec.ResourceHttpMessageWriter;
|
||||
import org.springframework.http.codec.ServerSentEventHttpMessageReader;
|
||||
import org.springframework.http.codec.ServerSentEventHttpMessageWriter;
|
||||
import org.springframework.http.codec.json.AbstractJackson2Decoder;
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
@@ -139,6 +141,9 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
||||
@Nullable
|
||||
private Encoder<?> kotlinSerializationJsonEncoder;
|
||||
|
||||
@Nullable
|
||||
private Consumer<Object> codecConsumer;
|
||||
|
||||
@Nullable
|
||||
private Integer maxInMemorySize;
|
||||
|
||||
@@ -196,6 +201,7 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
||||
this.jaxb2Encoder = other.jaxb2Encoder;
|
||||
this.kotlinSerializationJsonDecoder = other.kotlinSerializationJsonDecoder;
|
||||
this.kotlinSerializationJsonEncoder = other.kotlinSerializationJsonEncoder;
|
||||
this.codecConsumer = other.codecConsumer;
|
||||
this.maxInMemorySize = other.maxInMemorySize;
|
||||
this.enableLoggingRequestDetails = other.enableLoggingRequestDetails;
|
||||
this.registerDefaults = other.registerDefaults;
|
||||
@@ -265,6 +271,14 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
||||
initObjectWriters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureDefaultCodec(Consumer<Object> codecConsumer) {
|
||||
this.codecConsumer = (this.codecConsumer != null ?
|
||||
this.codecConsumer.andThen(codecConsumer) : codecConsumer);
|
||||
initReaders();
|
||||
initWriters();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maxInMemorySize(int byteCount) {
|
||||
if (!ObjectUtils.nullSafeEquals(this.maxInMemorySize, byteCount)) {
|
||||
@@ -359,6 +373,9 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
||||
if (codec instanceof DecoderHttpMessageReader) {
|
||||
codec = ((DecoderHttpMessageReader) codec).getDecoder();
|
||||
}
|
||||
else if (codec instanceof EncoderHttpMessageWriter) {
|
||||
codec = ((EncoderHttpMessageWriter<?>) codec).getEncoder();
|
||||
}
|
||||
|
||||
if (codec == null) {
|
||||
return;
|
||||
@@ -394,7 +411,6 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
||||
}
|
||||
if (codec instanceof ServerSentEventHttpMessageReader) {
|
||||
((ServerSentEventHttpMessageReader) codec).setMaxInMemorySize(size);
|
||||
initCodec(((ServerSentEventHttpMessageReader) codec).getDecoder());
|
||||
}
|
||||
if (codec instanceof DefaultPartHttpMessageReader) {
|
||||
((DefaultPartHttpMessageReader) codec).setMaxInMemorySize(size);
|
||||
@@ -430,12 +446,23 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
||||
}
|
||||
}
|
||||
|
||||
if (this.codecConsumer != null) {
|
||||
this.codecConsumer.accept(codec);
|
||||
}
|
||||
|
||||
// Recurse for nested codecs
|
||||
if (codec instanceof MultipartHttpMessageReader) {
|
||||
initCodec(((MultipartHttpMessageReader) codec).getPartReader());
|
||||
}
|
||||
else if (codec instanceof MultipartHttpMessageWriter) {
|
||||
initCodec(((MultipartHttpMessageWriter) codec).getFormWriter());
|
||||
}
|
||||
else if (codec instanceof ServerSentEventHttpMessageReader) {
|
||||
initCodec(((ServerSentEventHttpMessageReader) codec).getDecoder());
|
||||
}
|
||||
else if (codec instanceof ServerSentEventHttpMessageWriter) {
|
||||
initCodec(((ServerSentEventHttpMessageWriter) codec).getEncoder());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -521,22 +548,21 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
||||
/**
|
||||
* Return "base" typed writers only, i.e. common to client and server.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<HttpMessageWriter<?>> getBaseTypedWriters() {
|
||||
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()));
|
||||
addCodec(writers, new EncoderHttpMessageWriter<>(new ByteArrayEncoder()));
|
||||
addCodec(writers, new EncoderHttpMessageWriter<>(new ByteBufferEncoder()));
|
||||
addCodec(writers, new EncoderHttpMessageWriter<>(new DataBufferEncoder()));
|
||||
if (nettyByteBufPresent) {
|
||||
writers.add(new EncoderHttpMessageWriter<>(new NettyByteBufEncoder()));
|
||||
addCodec(writers, new EncoderHttpMessageWriter<>(new NettyByteBufEncoder()));
|
||||
}
|
||||
writers.add(new ResourceHttpMessageWriter());
|
||||
writers.add(new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly()));
|
||||
addCodec(writers, new ResourceHttpMessageWriter());
|
||||
addCodec(writers, new EncoderHttpMessageWriter<>(CharSequenceEncoder.textPlainOnly()));
|
||||
if (protobufPresent) {
|
||||
writers.add(new ProtobufHttpMessageWriter(this.protobufEncoder != null ?
|
||||
addCodec(writers, new ProtobufHttpMessageWriter(this.protobufEncoder != null ?
|
||||
(ProtobufEncoder) this.protobufEncoder : new ProtobufEncoder()));
|
||||
}
|
||||
return writers;
|
||||
@@ -574,17 +600,17 @@ class BaseDefaultCodecs implements CodecConfigurer.DefaultCodecs, CodecConfigure
|
||||
final List<HttpMessageWriter<?>> getBaseObjectWriters() {
|
||||
List<HttpMessageWriter<?>> writers = new ArrayList<>();
|
||||
if (kotlinSerializationJsonPresent) {
|
||||
writers.add(new EncoderHttpMessageWriter<>(getKotlinSerializationJsonEncoder()));
|
||||
addCodec(writers, new EncoderHttpMessageWriter<>(getKotlinSerializationJsonEncoder()));
|
||||
}
|
||||
if (jackson2Present) {
|
||||
writers.add(new EncoderHttpMessageWriter<>(getJackson2JsonEncoder()));
|
||||
addCodec(writers, new EncoderHttpMessageWriter<>(getJackson2JsonEncoder()));
|
||||
}
|
||||
if (jackson2SmilePresent) {
|
||||
writers.add(new EncoderHttpMessageWriter<>(this.jackson2SmileEncoder != null ?
|
||||
addCodec(writers, new EncoderHttpMessageWriter<>(this.jackson2SmileEncoder != null ?
|
||||
(Jackson2SmileEncoder) this.jackson2SmileEncoder : new Jackson2SmileEncoder()));
|
||||
}
|
||||
if (jaxb2Present && !shouldIgnoreXml) {
|
||||
writers.add(new EncoderHttpMessageWriter<>(this.jaxb2Encoder != null ?
|
||||
addCodec(writers, new EncoderHttpMessageWriter<>(this.jaxb2Encoder != null ?
|
||||
(Jaxb2XmlEncoder) this.jaxb2Encoder : new Jaxb2XmlEncoder()));
|
||||
}
|
||||
return writers;
|
||||
|
||||
Reference in New Issue
Block a user