Use HttpMessageConverters in client and server config
This commit uses the new `HttpMessageConverters` class for the HTTP client (`RestTemplate` and `RestClient`) and HTTP server support. This effectively removes the duplication of classpath detection for message converters in multiple places: clients, server and the multipart converter itself. Instead of creating multiple instances of the same converters, this allows applications to share converter instances as much as possible for better memory efficiency. As a result, this change also deprecates configuration methods in the MVC support that are superseded by the new methods introduced for `HttpMessageConverters` support. Closes gh-33894
This commit is contained in:
parent
1af25e9cb1
commit
beedf0a76b
|
@ -268,6 +268,7 @@ public class RouterFunctionMockMvcBuilder extends AbstractMockMvcBuilder<RouterF
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.addAll(messageConverters);
|
||||
}
|
||||
|
|
|
@ -470,6 +470,7 @@ public class StandaloneMockMvcBuilder extends AbstractMockMvcBuilder<StandaloneM
|
|||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.addAll(messageConverters);
|
||||
}
|
||||
|
|
|
@ -17,23 +17,8 @@
|
|||
package org.springframework.http.converter.support;
|
||||
|
||||
import org.springframework.http.converter.FormHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.JacksonCborHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.KotlinSerializationCborHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.protobuf.KotlinSerializationProtobufHttpMessageConverter;
|
||||
import org.springframework.http.converter.smile.JacksonSmileHttpMessageConverter;
|
||||
import org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.JacksonXmlHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
|
||||
import org.springframework.http.converter.yaml.JacksonYamlHttpMessageConverter;
|
||||
import org.springframework.http.converter.yaml.MappingJackson2YamlHttpMessageConverter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
|
||||
/**
|
||||
* Extension of {@link org.springframework.http.converter.FormHttpMessageConverter},
|
||||
|
@ -47,117 +32,24 @@ import org.springframework.util.ClassUtils;
|
|||
*/
|
||||
public class AllEncompassingFormHttpMessageConverter extends FormHttpMessageConverter {
|
||||
|
||||
private static final boolean jaxb2Present;
|
||||
|
||||
private static final boolean jacksonPresent;
|
||||
|
||||
private static final boolean jackson2Present;
|
||||
|
||||
private static final boolean jacksonXmlPresent;
|
||||
|
||||
private static final boolean jackson2XmlPresent;
|
||||
|
||||
private static final boolean jacksonSmilePresent;
|
||||
|
||||
private static final boolean jackson2SmilePresent;
|
||||
|
||||
private static final boolean jacksonCborPresent;
|
||||
|
||||
private static final boolean jackson2CborPresent;
|
||||
|
||||
private static final boolean jacksonYamlPresent;
|
||||
|
||||
private static final boolean jackson2YamlPresent;
|
||||
|
||||
private static final boolean gsonPresent;
|
||||
|
||||
private static final boolean jsonbPresent;
|
||||
|
||||
private static final boolean kotlinSerializationCborPresent;
|
||||
|
||||
private static final boolean kotlinSerializationJsonPresent;
|
||||
|
||||
private static final boolean kotlinSerializationProtobufPresent;
|
||||
|
||||
static {
|
||||
ClassLoader classLoader = AllEncompassingFormHttpMessageConverter.class.getClassLoader();
|
||||
jaxb2Present = ClassUtils.isPresent("jakarta.xml.bind.Binder", classLoader);
|
||||
jacksonPresent = ClassUtils.isPresent("tools.jackson.databind.ObjectMapper", classLoader);
|
||||
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
|
||||
jacksonXmlPresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.xml.XmlMapper", classLoader);
|
||||
jackson2XmlPresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
|
||||
jacksonSmilePresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.smile.SmileMapper", classLoader);
|
||||
jackson2SmilePresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
|
||||
jacksonCborPresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.cbor.CBORMapper", classLoader);
|
||||
jackson2CborPresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
|
||||
jacksonYamlPresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.yaml.YAMLMapper", classLoader);
|
||||
jackson2YamlPresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.yaml.YAMLFactory", classLoader);
|
||||
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
|
||||
jsonbPresent = ClassUtils.isPresent("jakarta.json.bind.Jsonb", classLoader);
|
||||
kotlinSerializationCborPresent = ClassUtils.isPresent("kotlinx.serialization.cbor.Cbor", classLoader);
|
||||
kotlinSerializationJsonPresent = ClassUtils.isPresent("kotlinx.serialization.json.Json", classLoader);
|
||||
kotlinSerializationProtobufPresent = ClassUtils.isPresent("kotlinx.serialization.protobuf.ProtoBuf", classLoader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@link AllEncompassingFormHttpMessageConverter} instance
|
||||
* that will auto-detect part converters.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
public AllEncompassingFormHttpMessageConverter() {
|
||||
HttpMessageConverters.withDefaults().build().forClient().forEach(this::addPartConverter);
|
||||
}
|
||||
|
||||
if (jaxb2Present && !jacksonXmlPresent && !jackson2XmlPresent) {
|
||||
addPartConverter(new Jaxb2RootElementHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonPresent) {
|
||||
addPartConverter(new JacksonJsonHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2Present) {
|
||||
addPartConverter(new MappingJackson2HttpMessageConverter());
|
||||
}
|
||||
else if (gsonPresent) {
|
||||
addPartConverter(new GsonHttpMessageConverter());
|
||||
}
|
||||
else if (jsonbPresent) {
|
||||
addPartConverter(new JsonbHttpMessageConverter());
|
||||
}
|
||||
else if (kotlinSerializationJsonPresent) {
|
||||
addPartConverter(new KotlinSerializationJsonHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonXmlPresent) {
|
||||
addPartConverter(new JacksonXmlHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2XmlPresent) {
|
||||
addPartConverter(new MappingJackson2XmlHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonSmilePresent) {
|
||||
addPartConverter(new JacksonSmileHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2SmilePresent) {
|
||||
addPartConverter(new MappingJackson2SmileHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonCborPresent) {
|
||||
addPartConverter(new JacksonCborHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2CborPresent) {
|
||||
addPartConverter(new MappingJackson2CborHttpMessageConverter());
|
||||
}
|
||||
else if (kotlinSerializationCborPresent) {
|
||||
addPartConverter(new KotlinSerializationCborHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonYamlPresent) {
|
||||
addPartConverter(new JacksonYamlHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2YamlPresent) {
|
||||
addPartConverter(new MappingJackson2YamlHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (kotlinSerializationProtobufPresent) {
|
||||
addPartConverter(new KotlinSerializationProtobufHttpMessageConverter());
|
||||
}
|
||||
/**
|
||||
* Create a new {@link AllEncompassingFormHttpMessageConverter} instance
|
||||
* using the given message converters.
|
||||
* @param converters the message converters to use for part conversion
|
||||
* @since 7.0
|
||||
*/
|
||||
public AllEncompassingFormHttpMessageConverter(Iterable<HttpMessageConverter<?>> converters) {
|
||||
converters.forEach(this::addPartConverter);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,29 +43,8 @@ import org.springframework.http.client.JettyClientHttpRequestFactory;
|
|||
import org.springframework.http.client.ReactorClientHttpRequestFactory;
|
||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
||||
import org.springframework.http.client.observation.ClientRequestObservationConvention;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.ResourceHttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.JacksonCborHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.KotlinSerializationCborHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
|
||||
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
|
||||
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.protobuf.KotlinSerializationProtobufHttpMessageConverter;
|
||||
import org.springframework.http.converter.smile.JacksonSmileHttpMessageConverter;
|
||||
import org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter;
|
||||
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.JacksonXmlHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
|
||||
import org.springframework.http.converter.yaml.JacksonYamlHttpMessageConverter;
|
||||
import org.springframework.http.converter.yaml.MappingJackson2YamlHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
@ -95,42 +74,6 @@ final class DefaultRestClientBuilder implements RestClient.Builder {
|
|||
|
||||
private static final boolean jdkClientPresent;
|
||||
|
||||
// message factories
|
||||
|
||||
private static final boolean romePresent;
|
||||
|
||||
private static final boolean jaxb2Present;
|
||||
|
||||
private static final boolean jacksonPresent;
|
||||
|
||||
private static final boolean jackson2Present;
|
||||
|
||||
private static final boolean jacksonXmlPresent;
|
||||
|
||||
private static final boolean jackson2XmlPresent;
|
||||
|
||||
private static final boolean jacksonSmilePresent;
|
||||
|
||||
private static final boolean jackson2SmilePresent;
|
||||
|
||||
private static final boolean jacksonCborPresent;
|
||||
|
||||
private static final boolean jackson2CborPresent;
|
||||
|
||||
private static final boolean jacksonYamlPresent;
|
||||
|
||||
private static final boolean jackson2YamlPresent;
|
||||
|
||||
private static final boolean gsonPresent;
|
||||
|
||||
private static final boolean jsonbPresent;
|
||||
|
||||
private static final boolean kotlinSerializationCborPresent;
|
||||
|
||||
private static final boolean kotlinSerializationJsonPresent;
|
||||
|
||||
private static final boolean kotlinSerializationProtobufPresent;
|
||||
|
||||
static {
|
||||
ClassLoader loader = DefaultRestClientBuilder.class.getClassLoader();
|
||||
|
||||
|
@ -138,25 +81,6 @@ final class DefaultRestClientBuilder implements RestClient.Builder {
|
|||
jettyClientPresent = ClassUtils.isPresent("org.eclipse.jetty.client.HttpClient", loader);
|
||||
reactorNettyClientPresent = ClassUtils.isPresent("reactor.netty.http.client.HttpClient", loader);
|
||||
jdkClientPresent = ClassUtils.isPresent("java.net.http.HttpClient", loader);
|
||||
|
||||
romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", loader);
|
||||
jaxb2Present = ClassUtils.isPresent("jakarta.xml.bind.Binder", loader);
|
||||
jacksonPresent = ClassUtils.isPresent("tools.jackson.databind.ObjectMapper", loader);
|
||||
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", loader) &&
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", loader);
|
||||
jacksonXmlPresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.xml.XmlMapper", loader);
|
||||
jackson2XmlPresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", loader);
|
||||
jacksonSmilePresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.smile.SmileMapper", loader);
|
||||
jackson2SmilePresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", loader);
|
||||
jacksonCborPresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.cbor.CBORMapper", loader);
|
||||
jackson2CborPresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", loader);
|
||||
jacksonYamlPresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.yaml.YAMLMapper", loader);
|
||||
jackson2YamlPresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.yaml.YAMLFactory", loader);
|
||||
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", loader);
|
||||
jsonbPresent = ClassUtils.isPresent("jakarta.json.bind.Jsonb", loader);
|
||||
kotlinSerializationCborPresent = ClassUtils.isPresent("kotlinx.serialization.cbor.Cbor", loader);
|
||||
kotlinSerializationJsonPresent = ClassUtils.isPresent("kotlinx.serialization.json.Json", loader);
|
||||
kotlinSerializationProtobufPresent = ClassUtils.isPresent("kotlinx.serialization.protobuf.ProtoBuf", loader);
|
||||
}
|
||||
|
||||
private @Nullable String baseUrl;
|
||||
|
@ -444,9 +368,11 @@ final class DefaultRestClientBuilder implements RestClient.Builder {
|
|||
}
|
||||
|
||||
@Override
|
||||
public RestClient.Builder messageConverters(List<HttpMessageConverter<?>> messageConverters) {
|
||||
public RestClient.Builder messageConverters(Iterable<HttpMessageConverter<?>> messageConverters) {
|
||||
validateConverters(messageConverters);
|
||||
this.messageConverters = Collections.unmodifiableList(messageConverters);
|
||||
List<HttpMessageConverter<?>> converters = new ArrayList<>();
|
||||
messageConverters.forEach(converter -> converters.add(converter));
|
||||
this.messageConverters = Collections.unmodifiableList(converters);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -473,77 +399,16 @@ final class DefaultRestClientBuilder implements RestClient.Builder {
|
|||
private List<HttpMessageConverter<?>> initMessageConverters() {
|
||||
if (this.messageConverters == null) {
|
||||
this.messageConverters = new ArrayList<>();
|
||||
|
||||
this.messageConverters.add(new ByteArrayHttpMessageConverter());
|
||||
this.messageConverters.add(new StringHttpMessageConverter());
|
||||
this.messageConverters.add(new ResourceHttpMessageConverter(false));
|
||||
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
|
||||
|
||||
if (romePresent) {
|
||||
this.messageConverters.add(new AtomFeedHttpMessageConverter());
|
||||
this.messageConverters.add(new RssChannelHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonXmlPresent) {
|
||||
this.messageConverters.add(new JacksonXmlHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2XmlPresent) {
|
||||
this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
|
||||
}
|
||||
else if (jaxb2Present) {
|
||||
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (kotlinSerializationProtobufPresent) {
|
||||
this.messageConverters.add(new KotlinSerializationProtobufHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonPresent) {
|
||||
this.messageConverters.add(new JacksonJsonHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2Present) {
|
||||
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
|
||||
}
|
||||
else if (gsonPresent) {
|
||||
this.messageConverters.add(new GsonHttpMessageConverter());
|
||||
}
|
||||
else if (jsonbPresent) {
|
||||
this.messageConverters.add(new JsonbHttpMessageConverter());
|
||||
}
|
||||
else if (kotlinSerializationJsonPresent) {
|
||||
this.messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonSmilePresent) {
|
||||
this.messageConverters.add(new JacksonSmileHttpMessageConverter());
|
||||
}
|
||||
if (jackson2SmilePresent) {
|
||||
this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonCborPresent) {
|
||||
this.messageConverters.add(new JacksonCborHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2CborPresent) {
|
||||
this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
|
||||
}
|
||||
else if (kotlinSerializationCborPresent) {
|
||||
this.messageConverters.add(new KotlinSerializationCborHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonYamlPresent) {
|
||||
this.messageConverters.add(new JacksonYamlHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2YamlPresent) {
|
||||
this.messageConverters.add(new MappingJackson2YamlHttpMessageConverter());
|
||||
}
|
||||
HttpMessageConverters.withDefaults().build().forClient().forEach(this.messageConverters::add);
|
||||
}
|
||||
return this.messageConverters;
|
||||
}
|
||||
|
||||
private void validateConverters(@Nullable List<HttpMessageConverter<?>> messageConverters) {
|
||||
Assert.notEmpty(messageConverters, "At least one HttpMessageConverter is required");
|
||||
Assert.noNullElements(messageConverters, "The HttpMessageConverter list must not contain null elements");
|
||||
private void validateConverters(@Nullable Iterable<HttpMessageConverter<?>> messageConverters) {
|
||||
Assert.notNull(messageConverters, "At least one HttpMessageConverter is required");
|
||||
Assert.isTrue(messageConverters.iterator().hasNext(), "At least one HttpMessageConverter is required");
|
||||
messageConverters.forEach(converter ->
|
||||
Assert.notNull(converter, "The HttpMessageConverter list must not contain null elements"));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -450,7 +450,7 @@ public interface RestClient {
|
|||
* @param configurer the configurer to apply on the list of default
|
||||
* {@link HttpMessageConverter} pre-initialized
|
||||
* @return this builder
|
||||
* @see #messageConverters(List)
|
||||
* @see #messageConverters(Iterable)
|
||||
*/
|
||||
Builder messageConverters(Consumer<List<HttpMessageConverter<?>>> configurer);
|
||||
|
||||
|
@ -461,7 +461,7 @@ public interface RestClient {
|
|||
* @since 6.2
|
||||
* @see #messageConverters(Consumer)
|
||||
*/
|
||||
Builder messageConverters(List<HttpMessageConverter<?>> messageConverters);
|
||||
Builder messageConverters(Iterable<HttpMessageConverter<?>> messageConverters);
|
||||
|
||||
/**
|
||||
* Configure the {@link io.micrometer.observation.ObservationRegistry} to use
|
||||
|
|
|
@ -50,33 +50,11 @@ import org.springframework.http.client.observation.ClientRequestObservationConte
|
|||
import org.springframework.http.client.observation.ClientRequestObservationConvention;
|
||||
import org.springframework.http.client.observation.DefaultClientRequestObservationConvention;
|
||||
import org.springframework.http.client.support.InterceptingHttpAccessor;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
import org.springframework.http.converter.GenericHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.ResourceHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
import org.springframework.http.converter.SmartHttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.JacksonCborHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.KotlinSerializationCborHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
|
||||
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
|
||||
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.protobuf.KotlinSerializationProtobufHttpMessageConverter;
|
||||
import org.springframework.http.converter.smile.JacksonSmileHttpMessageConverter;
|
||||
import org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter;
|
||||
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.JacksonXmlHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
|
||||
import org.springframework.http.converter.yaml.JacksonYamlHttpMessageConverter;
|
||||
import org.springframework.http.converter.yaml.MappingJackson2YamlHttpMessageConverter;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
import org.springframework.web.util.DefaultUriBuilderFactory;
|
||||
import org.springframework.web.util.DefaultUriBuilderFactory.EncodingMode;
|
||||
|
@ -125,65 +103,8 @@ import org.springframework.web.util.UriTemplateHandler;
|
|||
*/
|
||||
public class RestTemplate extends InterceptingHttpAccessor implements RestOperations {
|
||||
|
||||
private static final boolean romePresent;
|
||||
|
||||
private static final boolean jaxb2Present;
|
||||
|
||||
private static final boolean jacksonPresent;
|
||||
|
||||
private static final boolean jackson2Present;
|
||||
|
||||
private static final boolean jacksonXmlPresent;
|
||||
|
||||
private static final boolean jackson2XmlPresent;
|
||||
|
||||
private static final boolean jacksonSmilePresent;
|
||||
|
||||
private static final boolean jackson2SmilePresent;
|
||||
|
||||
private static final boolean jacksonCborPresent;
|
||||
|
||||
private static final boolean jackson2CborPresent;
|
||||
|
||||
private static final boolean jacksonYamlPresent;
|
||||
|
||||
private static final boolean jackson2YamlPresent;
|
||||
|
||||
private static final boolean gsonPresent;
|
||||
|
||||
private static final boolean jsonbPresent;
|
||||
|
||||
private static final boolean kotlinSerializationCborPresent;
|
||||
|
||||
private static final boolean kotlinSerializationJsonPresent;
|
||||
|
||||
private static final boolean kotlinSerializationProtobufPresent;
|
||||
|
||||
private static final ClientRequestObservationConvention DEFAULT_OBSERVATION_CONVENTION = new DefaultClientRequestObservationConvention();
|
||||
|
||||
static {
|
||||
ClassLoader classLoader = RestTemplate.class.getClassLoader();
|
||||
|
||||
romePresent = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed", classLoader);
|
||||
jaxb2Present = ClassUtils.isPresent("jakarta.xml.bind.Binder", classLoader);
|
||||
jacksonPresent = ClassUtils.isPresent("tools.jackson.databind.ObjectMapper", classLoader);
|
||||
jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) &&
|
||||
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader);
|
||||
jacksonXmlPresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.xml.XmlMapper", classLoader);
|
||||
jackson2XmlPresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.xml.XmlMapper", classLoader);
|
||||
jacksonSmilePresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.smile.SmileMapper", classLoader);
|
||||
jackson2SmilePresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.smile.SmileFactory", classLoader);
|
||||
jacksonCborPresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.cbor.CBORMapper", classLoader);
|
||||
jackson2CborPresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.cbor.CBORFactory", classLoader);
|
||||
jacksonYamlPresent = jacksonPresent && ClassUtils.isPresent("tools.jackson.dataformat.yaml.YAMLMapper", classLoader);
|
||||
jackson2YamlPresent = jackson2Present && ClassUtils.isPresent("com.fasterxml.jackson.dataformat.yaml.YAMLFactory", classLoader);
|
||||
gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader);
|
||||
jsonbPresent = ClassUtils.isPresent("jakarta.json.bind.Jsonb", classLoader);
|
||||
kotlinSerializationCborPresent = ClassUtils.isPresent("kotlinx.serialization.cbor.Cbor", classLoader);
|
||||
kotlinSerializationJsonPresent = ClassUtils.isPresent("kotlinx.serialization.json.Json", classLoader);
|
||||
kotlinSerializationProtobufPresent = ClassUtils.isPresent("kotlinx.serialization.protobuf.ProtoBuf", classLoader);
|
||||
}
|
||||
|
||||
|
||||
private final List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
|
||||
|
||||
|
@ -202,72 +123,8 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
|||
* Create a new instance with default settings.
|
||||
* Default {@link HttpMessageConverter HttpMessageConverters} are initialized.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
public RestTemplate() {
|
||||
this.messageConverters.add(new ByteArrayHttpMessageConverter());
|
||||
this.messageConverters.add(new StringHttpMessageConverter());
|
||||
this.messageConverters.add(new ResourceHttpMessageConverter(false));
|
||||
this.messageConverters.add(new AllEncompassingFormHttpMessageConverter());
|
||||
|
||||
if (romePresent) {
|
||||
this.messageConverters.add(new AtomFeedHttpMessageConverter());
|
||||
this.messageConverters.add(new RssChannelHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonXmlPresent) {
|
||||
this.messageConverters.add(new JacksonXmlHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2XmlPresent) {
|
||||
this.messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
|
||||
}
|
||||
else if (jaxb2Present) {
|
||||
this.messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (kotlinSerializationProtobufPresent) {
|
||||
this.messageConverters.add(new KotlinSerializationProtobufHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonPresent) {
|
||||
this.messageConverters.add(new JacksonJsonHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2Present) {
|
||||
this.messageConverters.add(new MappingJackson2HttpMessageConverter());
|
||||
}
|
||||
else if (gsonPresent) {
|
||||
this.messageConverters.add(new GsonHttpMessageConverter());
|
||||
}
|
||||
else if (jsonbPresent) {
|
||||
this.messageConverters.add(new JsonbHttpMessageConverter());
|
||||
}
|
||||
else if (kotlinSerializationJsonPresent) {
|
||||
this.messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonSmilePresent) {
|
||||
this.messageConverters.add(new JacksonSmileHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2SmilePresent) {
|
||||
this.messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonCborPresent) {
|
||||
this.messageConverters.add(new JacksonCborHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2CborPresent) {
|
||||
this.messageConverters.add(new MappingJackson2CborHttpMessageConverter());
|
||||
}
|
||||
else if (kotlinSerializationCborPresent) {
|
||||
this.messageConverters.add(new KotlinSerializationCborHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonYamlPresent) {
|
||||
this.messageConverters.add(new JacksonYamlHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2YamlPresent) {
|
||||
this.messageConverters.add(new MappingJackson2YamlHttpMessageConverter());
|
||||
}
|
||||
|
||||
HttpMessageConverters.withDefaults().build().forClient().forEach(this.messageConverters::add);
|
||||
updateErrorHandlerConverters();
|
||||
this.uriTemplateHandler = initUriTemplateHandler();
|
||||
}
|
||||
|
@ -288,9 +145,9 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
|||
* @param messageConverters the list of converters to use
|
||||
* @since 3.2.7
|
||||
*/
|
||||
public RestTemplate(List<HttpMessageConverter<?>> messageConverters) {
|
||||
public RestTemplate(Iterable<HttpMessageConverter<?>> messageConverters) {
|
||||
validateConverters(messageConverters);
|
||||
this.messageConverters.addAll(messageConverters);
|
||||
messageConverters.forEach(this.messageConverters::add);
|
||||
this.uriTemplateHandler = initUriTemplateHandler();
|
||||
updateErrorHandlerConverters();
|
||||
}
|
||||
|
@ -323,9 +180,11 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
|||
updateErrorHandlerConverters();
|
||||
}
|
||||
|
||||
private void validateConverters(List<HttpMessageConverter<?>> messageConverters) {
|
||||
Assert.notEmpty(messageConverters, "At least one HttpMessageConverter is required");
|
||||
Assert.noNullElements(messageConverters, "The HttpMessageConverter list must not contain null elements");
|
||||
private void validateConverters(Iterable<HttpMessageConverter<?>> messageConverters) {
|
||||
Assert.notNull(messageConverters, "At least one HttpMessageConverter is required");
|
||||
Assert.isTrue(messageConverters.iterator().hasNext(), "At least one HttpMessageConverter is required");
|
||||
messageConverters.forEach(converter ->
|
||||
Assert.notNull(converter, "The HttpMessageConverter list must not contain null elements"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.validation.MessageCodesResolver;
|
||||
import org.springframework.validation.Validator;
|
||||
|
@ -121,11 +122,20 @@ public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void configureMessageConverters(HttpMessageConverters.Builder builder) {
|
||||
this.configurers.configureMessageConverters(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
this.configurers.configureMessageConverters(converters);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
this.configurers.extendMessageConverters(converters);
|
||||
}
|
||||
|
|
|
@ -39,31 +39,8 @@ import org.springframework.format.FormatterRegistry;
|
|||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.ResourceHttpMessageConverter;
|
||||
import org.springframework.http.converter.ResourceRegionHttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.JacksonCborHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.KotlinSerializationCborHttpMessageConverter;
|
||||
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
|
||||
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
|
||||
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.GsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.KotlinSerializationJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||
import org.springframework.http.converter.protobuf.KotlinSerializationProtobufHttpMessageConverter;
|
||||
import org.springframework.http.converter.smile.JacksonSmileHttpMessageConverter;
|
||||
import org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter;
|
||||
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.JacksonXmlHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
|
||||
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
|
||||
import org.springframework.http.converter.yaml.JacksonYamlHttpMessageConverter;
|
||||
import org.springframework.http.converter.yaml.MappingJackson2YamlHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
@ -906,15 +883,41 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
|||
return this.messageConverters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override this method to add custom {@link HttpMessageConverter HttpMessageConverters}
|
||||
* Override this method to create a custom {@link HttpMessageConverters}.
|
||||
* Converters will be used with the
|
||||
* {@link RequestMappingHandlerAdapter} and the {@link ExceptionHandlerExceptionResolver}.
|
||||
* <p>By default, this will create an instance with default message converters registered,
|
||||
* if present on the classpath.
|
||||
* @since 7.0
|
||||
*/
|
||||
protected HttpMessageConverters createMessageConverters() {
|
||||
HttpMessageConverters.Builder builder = HttpMessageConverters.withDefaults();
|
||||
configureMessageConverters(builder);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to configure the message converters on the given
|
||||
* {@link HttpMessageConverters.Builder builder}.
|
||||
* @param builder the {@code HttpMessageConverters} builder to configure
|
||||
* @since 7.0
|
||||
*/
|
||||
protected void configureMessageConverters(HttpMessageConverters.Builder builder) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to add custom {@link HttpMessageConverter messsage converters}
|
||||
* to use with the {@link RequestMappingHandlerAdapter} and the
|
||||
* {@link ExceptionHandlerExceptionResolver}.
|
||||
* <p>Adding converters to the list turns off the default converters that would
|
||||
* otherwise be registered by default. Also see {@link #addDefaultHttpMessageConverters}
|
||||
* for adding default message converters.
|
||||
* @param converters a list to add message converters to (initially an empty list)
|
||||
* @deprecated since 7.0 in favor of {@link #configureMessageConverters(HttpMessageConverters.Builder)}
|
||||
*/
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
}
|
||||
|
||||
|
@ -924,7 +927,9 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
|||
* to be registered and then insert a custom converter through this method.
|
||||
* @param converters the list of configured converters to extend
|
||||
* @since 4.1.3
|
||||
* @deprecated since 7.0 in favor of {@link #configureMessageConverters(HttpMessageConverters.Builder)}
|
||||
*/
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
}
|
||||
|
||||
|
@ -932,93 +937,12 @@ public class WebMvcConfigurationSupport implements ApplicationContextAware, Serv
|
|||
* Adds a set of default HttpMessageConverter instances to the given list.
|
||||
* Subclasses can call this method from {@link #configureMessageConverters}.
|
||||
* @param messageConverters the list to add the default message converters to
|
||||
* @deprecated since 7.0 in favor of {@link #createMessageConverters()}
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
|
||||
messageConverters.add(new ByteArrayHttpMessageConverter());
|
||||
messageConverters.add(new StringHttpMessageConverter());
|
||||
messageConverters.add(new ResourceHttpMessageConverter());
|
||||
messageConverters.add(new ResourceRegionHttpMessageConverter());
|
||||
messageConverters.add(new AllEncompassingFormHttpMessageConverter());
|
||||
|
||||
if (romePresent) {
|
||||
messageConverters.add(new AtomFeedHttpMessageConverter());
|
||||
messageConverters.add(new RssChannelHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonXmlPresent) {
|
||||
messageConverters.add(new JacksonXmlHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2XmlPresent) {
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.xml();
|
||||
if (this.applicationContext != null) {
|
||||
builder.applicationContext(this.applicationContext);
|
||||
}
|
||||
messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.build()));
|
||||
}
|
||||
else if (jaxb2Present) {
|
||||
messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (kotlinSerializationProtobufPresent) {
|
||||
messageConverters.add(new KotlinSerializationProtobufHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonPresent) {
|
||||
messageConverters.add(new JacksonJsonHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2Present) {
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
|
||||
if (this.applicationContext != null) {
|
||||
builder.applicationContext(this.applicationContext);
|
||||
}
|
||||
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
|
||||
}
|
||||
else if (gsonPresent) {
|
||||
messageConverters.add(new GsonHttpMessageConverter());
|
||||
}
|
||||
else if (jsonbPresent) {
|
||||
messageConverters.add(new JsonbHttpMessageConverter());
|
||||
}
|
||||
else if (kotlinSerializationJsonPresent) {
|
||||
messageConverters.add(new KotlinSerializationJsonHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonSmilePresent) {
|
||||
messageConverters.add(new JacksonSmileHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2SmilePresent) {
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.smile();
|
||||
if (this.applicationContext != null) {
|
||||
builder.applicationContext(this.applicationContext);
|
||||
}
|
||||
messageConverters.add(new MappingJackson2SmileHttpMessageConverter(builder.build()));
|
||||
}
|
||||
|
||||
if (jacksonCborPresent) {
|
||||
messageConverters.add(new JacksonCborHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2CborPresent) {
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.cbor();
|
||||
if (this.applicationContext != null) {
|
||||
builder.applicationContext(this.applicationContext);
|
||||
}
|
||||
messageConverters.add(new MappingJackson2CborHttpMessageConverter(builder.build()));
|
||||
}
|
||||
else if (kotlinSerializationCborPresent) {
|
||||
messageConverters.add(new KotlinSerializationCborHttpMessageConverter());
|
||||
}
|
||||
|
||||
if (jacksonYamlPresent) {
|
||||
messageConverters.add(new JacksonYamlHttpMessageConverter());
|
||||
}
|
||||
else if (jackson2YamlPresent) {
|
||||
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.yaml();
|
||||
if (this.applicationContext != null) {
|
||||
builder.applicationContext(this.applicationContext);
|
||||
}
|
||||
messageConverters.add(new MappingJackson2YamlHttpMessageConverter(builder.build()));
|
||||
}
|
||||
HttpMessageConverters converters = createMessageConverters();
|
||||
converters.forServer().forEach(messageConverters::add);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.springframework.core.convert.converter.Converter;
|
|||
import org.springframework.format.Formatter;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
import org.springframework.validation.MessageCodesResolver;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.web.ErrorResponse;
|
||||
|
@ -171,6 +172,14 @@ public interface WebMvcConfigurer {
|
|||
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link HttpMessageConverters} instance being built.
|
||||
* @param builder the builder to configure
|
||||
* @since 7.0
|
||||
*/
|
||||
default void configureMessageConverters(HttpMessageConverters.Builder builder) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the {@link HttpMessageConverter HttpMessageConverter}s for
|
||||
* reading from the request body and for writing to the response body.
|
||||
|
@ -186,20 +195,24 @@ public interface WebMvcConfigurer {
|
|||
* {@link #extendMessageConverters(java.util.List)} to modify the configured
|
||||
* list of message converters.
|
||||
* @param converters initially an empty list of converters
|
||||
* @deprecated since 7.0 in favor of configuring converters on {@link #configureMessageConverters(HttpMessageConverters.Builder)}
|
||||
*/
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Extend or modify the list of converters after it has been, either
|
||||
* {@link #configureMessageConverters(List) configured} or initialized with
|
||||
* {@link #configureMessageConverters(List) configured}, or initialized with
|
||||
* a default list.
|
||||
* <p>Note that the order of converter registration is important. Especially
|
||||
* in cases where clients accept {@link org.springframework.http.MediaType#ALL}
|
||||
* the converters configured earlier will be preferred.
|
||||
* @param converters the list of configured converters to be extended
|
||||
* @since 4.1.3
|
||||
* @deprecated since 7.0 in favor of configuring converters on {@link #configureMessageConverters(HttpMessageConverters.Builder)}
|
||||
*/
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.jspecify.annotations.Nullable;
|
|||
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.validation.MessageCodesResolver;
|
||||
import org.springframework.validation.Validator;
|
||||
|
@ -141,6 +142,15 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void configureMessageConverters(HttpMessageConverters.Builder builder) {
|
||||
for (WebMvcConfigurer delegate : this.delegates) {
|
||||
delegate.configureMessageConverters(builder);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
for (WebMvcConfigurer delegate : this.delegates) {
|
||||
delegate.configureMessageConverters(converters);
|
||||
|
@ -148,6 +158,8 @@ class WebMvcConfigurerComposite implements WebMvcConfigurer {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Deprecated(since = "7.0", forRemoval = true)
|
||||
@SuppressWarnings("removal")
|
||||
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
for (WebMvcConfigurer delegate : this.delegates) {
|
||||
delegate.extendMessageConverters(converters);
|
||||
|
|
|
@ -29,7 +29,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
|
|||
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.validation.DefaultMessageCodesResolver;
|
||||
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
|
||||
|
@ -92,6 +92,7 @@ public class DelegatingWebMvcConfigurationTests {
|
|||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("removal")
|
||||
void requestMappingHandlerAdapter() {
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
RequestMappingHandlerAdapter adapter = this.webMvcConfig.requestMappingHandlerAdapter(
|
||||
|
@ -122,16 +123,11 @@ public class DelegatingWebMvcConfigurationTests {
|
|||
@Test
|
||||
void configureMessageConverters() {
|
||||
HttpMessageConverter<?> customConverter = mock();
|
||||
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter();
|
||||
WebMvcConfigurer configurer = new WebMvcConfigurer() {
|
||||
@Override
|
||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.add(stringConverter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.add(0, customConverter);
|
||||
public void configureMessageConverters(HttpMessageConverters.Builder builder) {
|
||||
builder.additionalMessageConverter(customConverter);
|
||||
}
|
||||
};
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(configurer));
|
||||
|
@ -141,9 +137,7 @@ public class DelegatingWebMvcConfigurationTests {
|
|||
this.webMvcConfig.mvcConversionService(),
|
||||
this.webMvcConfig.mvcValidator());
|
||||
|
||||
assertThat(adapter.getMessageConverters()).as("One custom converter expected").hasSize(2);
|
||||
assertThat(adapter.getMessageConverters()).element(0).isSameAs(customConverter);
|
||||
assertThat(adapter.getMessageConverters()).element(1).isSameAs(stringConverter);
|
||||
assertThat(adapter.getMessageConverters()).as("One custom converter expected").contains(customConverter);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -167,6 +161,7 @@ public class DelegatingWebMvcConfigurationTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("removal")
|
||||
void handlerExceptionResolver() {
|
||||
webMvcConfig.setConfigurers(Collections.singletonList(webMvcConfigurer));
|
||||
webMvcConfig.handlerExceptionResolver(webMvcConfig.mvcContentNegotiationManager());
|
||||
|
|
|
@ -36,8 +36,10 @@ import org.springframework.core.io.FileSystemResourceLoader;
|
|||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageConverters;
|
||||
import org.springframework.http.converter.StringHttpMessageConverter;
|
||||
import org.springframework.http.converter.json.JacksonJsonHttpMessageConverter;
|
||||
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
|
||||
import org.springframework.scheduling.concurrent.ConcurrentTaskExecutor;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
@ -209,9 +211,10 @@ class WebMvcConfigurationSupportExtensionTests {
|
|||
|
||||
// Message converters
|
||||
List<HttpMessageConverter<?>> converters = adapter.getMessageConverters();
|
||||
assertThat(converters).hasSize(2);
|
||||
assertThat(converters).hasSize(3);
|
||||
assertThat(converters.get(0).getClass()).isEqualTo(StringHttpMessageConverter.class);
|
||||
assertThat(converters.get(1).getClass()).isEqualTo(JacksonJsonHttpMessageConverter.class);
|
||||
assertThat(converters.get(2).getClass()).isEqualTo(AllEncompassingFormHttpMessageConverter.class);
|
||||
ObjectMapper objectMapper = ((JacksonJsonHttpMessageConverter) converters.get(1)).getObjectMapper();
|
||||
assertThat(objectMapper.deserializationConfig().isEnabled(MapperFeature.DEFAULT_VIEW_INCLUSION)).isFalse();
|
||||
assertThat(objectMapper.deserializationConfig().isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)).isFalse();
|
||||
|
@ -347,6 +350,7 @@ class WebMvcConfigurationSupportExtensionTests {
|
|||
* plus WebMvcConfigurer can switch to extending WebMvcConfigurationSupport directly for
|
||||
* more advanced configuration needs.
|
||||
*/
|
||||
@SuppressWarnings("removal")
|
||||
private static class TestWebMvcConfigurationSupport extends WebMvcConfigurationSupport implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
|
@ -354,9 +358,17 @@ class WebMvcConfigurationSupportExtensionTests {
|
|||
registry.addConverter(TestBean.class, String.class, testBean -> "converted");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HttpMessageConverters createMessageConverters() {
|
||||
return HttpMessageConverters.create().jsonMessageConverter(new JacksonJsonHttpMessageConverter()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureMessageConverters(HttpMessageConverters.Builder builder) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
|
||||
converters.add(new JacksonJsonHttpMessageConverter());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue