mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-23 14:40:00 +00:00
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:
+16
-124
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-146
@@ -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"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user