1、在 pom.xml 里引入依赖:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency>

2、直接使用 new RestTemplate() 使用 RestTemplate:

示例代码(注意这有坑,下面解释):

String baiduHtml = new RestTemplate().getForObject("https://www.baidu.com", String.class);System.out.println(baiduHtml);

注:不能直接使用 @Autowired 自动注入 RestTemplate 使用。因为,官网文档有写:
Since RestTemplate instances often need to be customized before being used, Spring Boot does not provide any single auto-configured RestTemplate bean.
3、使用 RestTemplateBuilder,官网文档也有写,提供了自动配置的 RestTemplateBuilder,可以用 RestTemplateBuilder 创建 RestTemplate:
示例代码:

@Autowiredprivate RestTemplateBuilder restTemplateBuilder;@Autowiredprivate RestTemplate restTemplate;@Beanpublic RestTemplate getRestTemplate() { return restTemplateBuilder.build();}//调用方式:String baiduHtml = restTemplate.getForObject("https://www.baidu.com", String.class);System.out.println(baiduHtml);

这样处理之后(在 SpringBootApplication 入口中定义),在任何地方就可以直接使用自动配置的 RestTemplate 了。

4、编写配置类使用:

import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.web.client.RestTemplateBuilder;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;@Configurationpublic class RestTemplateConfig { @Autowired private RestTemplateBuilder restTemplateBuilder; @Bean public RestTemplate restTemplate(){ return restTemplateBuilder.build(); }}

然后就可以在其他地方直接使用 @Autowired 注入使用了。
通过以上三种方式(2、3、4)都可以使用 RestTemplate 访问第三方接口,但是上面说的有个坑,在这里:
使用 new RestTemplate() 和 RestTemplateBuilder 创建的 RestTemplate 访问的时候,编码有问题,我使用 new RestTemplate() 访问百度,得到乱码的HTML,但是使用 RestTemplateBuilder 创建的 RestTemplate 访问的时候,确是正常的!!!
来看源码,一探究竟:
通过集成 actuator 查看所有 beans 发现这么一个 Bean:

"restTemplateBuilder": { aliases: [ ], scope: "singleton", type: "org.springframework.boot.web.client.RestTemplateBuilder", resource: "class path resource [org/springframework/boot/autoconfigure/web/client/RestTemplateAutoConfiguration.class]", dependencies: [ ]}

根据 resource 找到这个 RestTemplateAutoConfiguration 类:

@Configuration@AutoConfigureAfter({HttpMessageConvertersAutoConfiguration.class})@ConditionalOnClass({RestTemplate.class})public class RestTemplateAutoConfiguration { private final ObjectProvider<HttpMessageConverters> messageConverters; private final ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers; public RestTemplateAutoConfiguration(ObjectProvider<HttpMessageConverters> messageConverters, ObjectProvider<RestTemplateCustomizer> restTemplateCustomizers) { this.messageConverters = messageConverters; this.restTemplateCustomizers = restTemplateCustomizers; } @Bean @ConditionalOnMissingBean public RestTemplateBuilder restTemplateBuilder() { RestTemplateBuilder builder = new RestTemplateBuilder(new RestTemplateCustomizer[0]); HttpMessageConverters converters = (HttpMessageConverters)this.messageConverters.getIfUnique(); if(converters != null) { builder = builder.messageConverters(converters.getConverters()); //↑ ↑ ↑ 看这里,猜测编码转换应该是这里加入了转换器 } List customizers = (List)this.restTemplateCustomizers.orderedStream().collect(Collectors.toList()); if(!CollectionUtils.isEmpty(customizers)) { builder = builder.customizers(customizers); } return builder; }}

看这个类上面有注解:

@AutoConfigureAfter({HttpMessageConvertersAutoConfiguration.class})

顾名思义,是在 HttpMessageConvertersAutoConfiguration 这个配置类之后配置此类。继续进入 HttpMessageConvertersAutoConfiguration 类:

@Configuration@ConditionalOnClass({HttpMessageConverter.class})@AutoConfigureAfter({GsonAutoConfiguration.class, JacksonAutoConfiguration.class, JsonbAutoConfiguration.class})@Import({JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class, JsonbHttpMessageConvertersConfiguration.class})public class HttpMessageConvertersAutoConfiguration { static final String PREFERRED_MAPPER_PROPERTY = "spring.http.converters.preferred-json-mapper"; private final List<HttpMessageConverter<?>> converters; public HttpMessageConvertersAutoConfiguration(ObjectProvider<HttpMessageConverter<?>> convertersProvider) { this.converters = (List)convertersProvider.orderedStream().collect(Collectors.toList()); } @Bean @ConditionalOnMissingBean public HttpMessageConverters messageConverters() { return new HttpMessageConverters(this.converters); } @Configuration @ConditionalOnClass({StringHttpMessageConverter.class}) @EnableConfigurationProperties({HttpProperties.class}) protected static class StringHttpMessageConverterConfiguration { private final Encoding properties; protected StringHttpMessageConverterConfiguration(HttpProperties httpProperties) { this.properties = httpProperties.getEncoding(); } @Bean @ConditionalOnMissingBean public StringHttpMessageConverter stringHttpMessageConverter() { StringHttpMessageConverter converter = new StringHttpMessageConverter(this.properties.getCharset()); converter.setWriteAcceptCharset(false); return converter; } }}

可以看到这个类中有一个 protected 的内部类,里面配置了名为 StringHttpMessageConverter 的 Bean,他内部使用了 HttpProperties.class 这个配置类里面的配置,再深入 HttpProperties 看看,代码过多,所以省略了很多:

@ConfigurationProperties( prefix = "spring.http")public class HttpProperties { private final HttpProperties.Encoding encoding = new HttpProperties.Encoding(); //...省略其他代码 public HttpProperties.Encoding getEncoding() { return this.encoding; } public static class Encoding { public static final Charset DEFAULT_CHARSET; private Charset charset; public Encoding() { this.charset = DEFAULT_CHARSET; } public Charset getCharset() { return this.charset; } //...省略其他代码 static { DEFAULT_CHARSET = StandardCharsets.UTF_8; } //...省略其他代码 }}

到这里似乎就渐渐明白了,如果使用 RestTemplateBuilder 创建的 RestTemplate,它默认就是用了 spring.http.encoding.charset 这个配置的编码。在 application.properties 中配置的时候,可以看到这个编码默认就是 UTF-8,截图如下:

那么我们来实验一下,修改 application.properties 增加配置:

spring.http.encoding.charset=ISO-8859-1

如果不出意外,使用 RestTemplateBuilder 创建的 RestTemplate 访问的时候应该是会是乱码。

@Autowired private RestTemplate restTemplate; private String getRestResponse(String url) { try { return new RestTemplate().getForObject(url, String.class); } catch(Exception ex) { return ex.toString(); } } private String getRestResponse2(String url) { try { return restTemplate.getForObject(url, String.class); } catch(Exception ex) { return ex.toString(); } } @Override public void run(ApplicationArguments applicationArguments) throws Exception { System.out.println(getRestResponse("https://www.baidu.com")); System.out.println(getRestResponse2("https://www.baidu.com")); }

此时,第二种方式获取到的百度源代码和第一种方式获取到的源代码一致,都是乱码,可见直接使用 new RestTemplate() 将使用默认编码 ISO-8859-1。
那么问题来了,如何在使用 new RestTemplate() 的时候同样是 UTF-8 编码呢?在创建 RestTemplate 之后做一点处理即可,代码如下:

private String getRestResponse(String url) { try { RestTemplate rest = new RestTemplate(); for (HttpMessageConverter<?> converter : rest.getMessageConverters()) { if (converter instanceof StringHttpMessageConverter) { ((StringHttpMessageConverter)converter).setDefaultCharset(Charset.forName("UTF-8")); break; } } return rest.getForObject(url, String.class); } catch(Exception ex) { return ex.toString(); } }

此时,RestTemplate 乱码问题已经得到解决。