SpringBoot RestTemplate 介绍

目录

  • 前言
  • [一、RestTemplate 是什么?](#一、RestTemplate 是什么?)
  • [二、RestTemplate 和 HttpClient 区别](#二、RestTemplate 和 HttpClient 区别)
  • 三、二者核心区别
  • [四、为什么很多 Spring Boot 项目喜欢用 RestTemplate?](#四、为什么很多 Spring Boot 项目喜欢用 RestTemplate?)
  • [五、RestTemplate 的工作原理](#五、RestTemplate 的工作原理)
  • [六、Spring Boot 如何引入 RestTemplate](#六、Spring Boot 如何引入 RestTemplate)
  • [七、Maven 引入](#七、Maven 引入)
  • [八、如何创建 RestTemplate](#八、如何创建 RestTemplate)
    • [1.RestTemplate 创建](#1.RestTemplate 创建)
    • [2.RestTemplate + Apache HttpClient 创建](#2.RestTemplate + Apache HttpClient 创建)
  • 九、为什么要放到@Bean里?
  • [十、RestTemplate 常用方法](#十、RestTemplate 常用方法)
  • [十一、GET 请求示例](#十一、GET 请求示例)
    • [1. 请求接口](#1. 请求接口)
    • [2. Java对象](#2. Java对象)
    • [3. GET调用](#3. GET调用)
  • [十二、GET 带参数](#十二、GET 带参数)
  • [十三、POST 请求示例](#十三、POST 请求示例)
    • [1. 请求接口](#1. 请求接口)
    • [2. 请求对象](#2. 请求对象)
    • [3. POST调用](#3. POST调用)
  • 十四、exchange()(推荐)
    • [1.GET 示例](#1.GET 示例)
    • [2.GET 请求 + token 示例](#2.GET 请求 + token 示例)
    • [3. POST 示例](#3. POST 示例)
    • [4.POST 请求 + token](#4.POST 请求 + token)
    • 5.简单文件下载(byte[])示例
    • [6. InputStream 文件下载(推荐)](#6. InputStream 文件下载(推荐))
  • 十五、如何获取文件名、文件类型、判断请求成功?
  • [十六、RestTemplate 支持哪些底层实现?](#十六、RestTemplate 支持哪些底层实现?)
  • [十七、RestTemplate 缺点](#十七、RestTemplate 缺点)
  • 十八、现在为什么还大量使用?
  • [十九、RestTemplate vs WebClient](#十九、RestTemplate vs WebClient)
  • [二十、什么时候用 RestTemplate?](#二十、什么时候用 RestTemplate?)
  • [二十一、什么时候用 WebClient?](#二十一、什么时候用 WebClient?)
  • 二十二、企业里真实情况
  • 二十三、学习路线
  • 二十四、一个完整实际案例

前言

RestTemplateHttpClient 都可以用于发送 HTTP 请求,但它们定位不同。

可以把它们理解成:

  • HttpClient:底层 HTTP 通信工具
  • RestTemplate:Spring 对 HttpClient 等工具的高级封装

一、RestTemplate 是什么?

RestTemplate 是 Spring 提供的一个:

  • 同步阻塞式 HTTP 客户端
  • 用于调用:
    • 微服务接口
    • 第三方 API
    • 文件下载
    • 外部系统通信

它本质上是:

text 复制代码
Spring 对 HTTP 请求进行了再次封装

让你:

  • 不用手动处理连接
  • 不用自己解析响应流
  • 不用自己转换 JSON

可以像调用普通方法一样发 HTTP 请求。


二、RestTemplate 和 HttpClient 区别

text 复制代码
业务代码
   ↓
RestTemplate
   ↓
ClientHttpRequestFactory
   ↓
HttpClient / OkHttp / JDK HttpURLConnection

也就是说:

text 复制代码
RestTemplate 是上层封装
HttpClient 是底层实现

三、二者核心区别

对比项 RestTemplate HttpClient
所属 Spring Apache
定位 高级HTTP工具 底层HTTP客户端
使用难度 简单 较复杂
JSON转换 自动 手动
与Spring整合 非常好 一般
学习成本
适合 微服务调用 底层定制
是否阻塞 有同步和异步
推荐状态 官方已维护模式 仍常用

四、为什么很多 Spring Boot 项目喜欢用 RestTemplate?

因为它:

  • 和 Spring 完美整合
  • 非常简单
  • 自动 JSON 转对象
  • 支持拦截器
  • 支持负载均衡
  • 支持超时配置
  • 支持统一异常处理

例如:

java 复制代码
User user = restTemplate.getForObject(url, User.class);

就直接得到 Java 对象了。

不用:

  • 创建连接
  • 读取 InputStream
  • Jackson 转换 JSON

五、RestTemplate 的工作原理

当你:

java 复制代码
restTemplate.getForObject(...)

时,内部会:

text 复制代码
1. 创建HTTP请求
2. 建立TCP连接
3. 发送请求
4. 获取响应
5. 自动解析JSON
6. 转换成Java对象

六、Spring Boot 如何引入 RestTemplate

其实:

text 复制代码
spring-web

里已经包含了。

Spring Boot Web 项目一般天然就有。


七、Maven 引入

如果没有,可以引入:

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

这里面已经包含:

  • Spring MVC
  • RestTemplate
  • Jackson

八、如何创建 RestTemplate

1.RestTemplate 创建

通常会放到配置类里。

java 复制代码
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
            SimpleClientHttpRequestFactory factory =
            new SimpleClientHttpRequestFactory();

    	// 连接超时
    	factory.setConnectTimeout(5000);
    	// 读取超时
    	factory.setReadTimeout(10000);
    	return new RestTemplate(factory);
    }
}

然后:

java 复制代码
@Autowired
private RestTemplate restTemplate;

即可使用。


2.RestTemplate + Apache HttpClient 创建

因为 RestTemplate 默认实现性能一般。

很多公司会:

text 复制代码
RestTemplate + Apache HttpClient

获得:

  • 连接池
  • 更高性能
  • 更稳定

示例:

java 复制代码
@Bean
public RestTemplate restTemplate() {
    RequestConfig config = RequestConfig.custom()
            //建立TCP连接最大等待时间。例如:服务器不存在、网络不通
            .setConnectTimeout(5000)
            //读取超时。连接成功后服务器迟迟不返回数据,等待多久。
            .setResponseTimeout(10000)
            .build();

    CloseableHttpClient httpClient =
            HttpClients.custom()
                    .setDefaultRequestConfig(config)
                    .build();

    HttpComponentsClientHttpRequestFactory factory =
            new HttpComponentsClientHttpRequestFactory(httpClient);

    return new RestTemplate(factory);
}

九、为什么要放到@Bean里?

因为 Spring 会:

  • 创建单例对象
  • 放入IOC容器
  • 全局复用
  • 自动注入

这样整个项目只会有一个 RestTemplate。


十、RestTemplate 常用方法

方法 作用
getForObject GET请求返回对象
getForEntity GET返回完整响应
postForObject POST返回对象
postForEntity POST返回完整响应
exchange 最强大的通用方法

十一、GET 请求示例


1. 请求接口

假设:

text 复制代码
GET http://localhost:8080/user/1

返回:

json 复制代码
{
  "id":1,
  "name":"Tom"
}

2. Java对象

java 复制代码
@Data
public class User {

    private Long id;

    private String name;
}

3. GET调用

java 复制代码
@Autowired
private RestTemplate restTemplate;

public void testGet() {

    String url = "http://localhost:8080/user/1";

    User user = restTemplate.getForObject(url, User.class);

    System.out.println(user);
}

十二、GET 带参数


方式1:拼接URL

java 复制代码
String url = "http://localhost:8080/user?id=1";

方式2:占位符(推荐)

java 复制代码
String url = "http://localhost:8080/user/{id}";

User user = restTemplate.getForObject(
        url,
        User.class,
        1
);

等价于:

text 复制代码
/user/1

十三、POST 请求示例


1. 请求接口

text 复制代码
POST /user/add

请求体:

json 复制代码
{
  "name":"Tom"
}

2. 请求对象

java 复制代码
@Data
public class UserReq {

    private String name;
}

3. POST调用

java 复制代码
public void testPost() {

    String url = "http://localhost:8080/user/add";

    UserReq req = new UserReq();
    req.setName("Tom");

    User user = restTemplate.postForObject(
            url,
            req,
            User.class
    );

    System.out.println(user);
}

十四、exchange()(推荐)

实际项目中:

text 复制代码
90% 会使用 exchange()

因为它:

  • 支持所有 HTTP 方法
  • 支持请求头
  • 支持 token
  • 支持文件上传
  • 支持复杂请求

1.GET 示例

java 复制代码
HttpHeaders headers = new HttpHeaders();
headers.add("token", "123456");

HttpEntity<Void> entity = new HttpEntity<>(headers);

ResponseEntity<User> response =
        restTemplate.exchange(
                "http://localhost:8080/user/1",
                HttpMethod.GET,
                entity,
                User.class
        );

User user = response.getBody();

2.GET 请求 + token 示例

java 复制代码
@Autowired
private RestTemplate restTemplate;

public void test() {

    String url = "http://localhost:8080/user/1";

    // 1. 创建请求头
    HttpHeaders headers = new HttpHeaders();

    // 2. 设置 token
    headers.set("Authorization", "Bearer abc123");

    // 3. 封装 HttpEntity
    HttpEntity<Void> entity =
            new HttpEntity<>(headers);

    // 4. 发起请求
    ResponseEntity<String> response =
            restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    String.class
            );

    // 5. 获取响应
    String body = response.getBody();

    System.out.println(body);
}

3. POST 示例

java 复制代码
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

UserReq req = new UserReq();
req.setName("Tom");

HttpEntity<UserReq> entity =
        new HttpEntity<>(req, headers);

ResponseEntity<User> response =
        restTemplate.exchange(
                "http://localhost:8080/user/add",
                HttpMethod.POST,
                entity,
                User.class
        );

User user = response.getBody();

4.POST 请求 + token

java 复制代码
public void testPost() {

    String url = "http://localhost:8080/order/create";

    // 请求头
    HttpHeaders headers = new HttpHeaders();

    headers.setContentType(MediaType.APPLICATION_JSON);

    headers.setBearerAuth("abc123");

    // 请求体
    Map<String, Object> body = new HashMap<>();
    body.put("name", "Tom");
    body.put("age", 18);

    // 封装
    HttpEntity<Map<String, Object>> entity =
            new HttpEntity<>(body, headers);

    // 请求
    ResponseEntity<String> response =
            restTemplate.exchange(
                    url,
                    HttpMethod.POST,
                    entity,
                    String.class
            );

    System.out.println(response.getBody());
}

setBearerAuth 是什么?

这个:

复制代码
headers.setBearerAuth("abc123");

等价于:

复制代码
Authorization: Bearer abc123

它是 Spring 专门提供的快捷方法。

如果不是 Bearer token 怎么办?

有些系统:

复制代码
token: xxx

或者:

复制代码
Authorization: xxx

那就:

复制代码
headers.set("token", "abc123");

或者:

复制代码
headers.set("Authorization", "abc123");

即可。

5.简单文件下载(byte[])示例

对于一些小文件可以使用字节数组来下载:

java 复制代码
public void download() throws Exception {

    String url =
            "http://localhost:8080/file/test.pdf";

    // 请求头
    HttpHeaders headers = new HttpHeaders();

    headers.setBearerAuth("abc123");

    HttpEntity<Void> entity =
            new HttpEntity<>(headers);

    // 请求
    ResponseEntity<byte[]> response =
            restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    byte[].class
            );

    // 获取文件字节
    byte[] bytes = response.getBody();

    // 保存文件
    Files.write(
            Paths.get("D:/test.pdf"),
            bytes
    );

    System.out.println("下载完成");
}

6. InputStream 文件下载(推荐)

上面的示例使用 byte[] 会一次性加载整个文件到内存,对于大文件 大文件:500MB 或者1GB 这样的文件 容易 OOM(内存溢出)。

更推荐下面的使用 Resource 和 inputStream 边读边写大文件,它不会一次性加载整个文件,更适合大文件

java 复制代码
public void download2() throws Exception {

    String url = "http://localhost:8080/file/big.zip";

    HttpHeaders headers = new HttpHeaders();

    headers.setBearerAuth("abc123");

    HttpEntity<Void> entity =
            new HttpEntity<>(headers);

    ResponseEntity<Resource> response =
            restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    Resource.class
            );

    // 获取输入流
    InputStream inputStream =
            response.getBody().getInputStream();

    // 输出流
    FileOutputStream out =
            new FileOutputStream("D:/big.zip");

    byte[] buffer = new byte[8192];

    int len;

    while ((len = inputStream.read(buffer)) != -1) {
        out.write(buffer, 0, len);
    }

    out.close();
    inputStream.close();

    System.out.println("下载成功");
}

十五、如何获取文件名、文件类型、判断请求成功?

HTTP 响应头里通常有:

java 复制代码
Content-Disposition

例如:

java 复制代码
Content-Disposition:
attachment; filename=test.pdf

获取文件名:

java 复制代码
String disposition = response.getHeaders().getFirst("Content-Disposition");

System.out.println(disposition);

获取 Content-Type:

java 复制代码
MediaType contentType = response.getHeaders().getContentType();

//application/pdf
System.out.println(contentType);

如何判断下载成功:

java 复制代码
if (response.getStatusCode() == HttpStatus.OK) {
    System.out.println("成功");
}

十六、RestTemplate 支持哪些底层实现?

默认:

text 复制代码
JDK HttpURLConnection

但也可以替换成:

  • Apache HttpClient(最常见)
  • OkHttp

例如:

java 复制代码
HttpComponentsClientHttpRequestFactory

底层用 HttpClient。


十七、RestTemplate 缺点

Spring 官方现在:

text 复制代码
已不再积极推荐 RestTemplate

而推荐:

text 复制代码
WebClient

原因:

  • RestTemplate 是阻塞式
  • 高并发性能一般
  • 不适合响应式

十八、现在为什么还大量使用?

因为:

  • 老项目太多
  • 简单稳定
  • 易于维护
  • 大量公司还在用

特别是:

text 复制代码
传统 Spring Boot 项目

仍然大量使用。


十九、RestTemplate vs WebClient

对比 RestTemplate WebClient
模型 同步阻塞 异步非阻塞
性能 一般
学习难度 简单 较高
使用广泛度 非常广 越来越广
推荐程度 维护模式 官方推荐

二十、什么时候用 RestTemplate?

适合:

  • 公司老项目
  • 普通微服务调用
  • 中小并发
  • 简单HTTP调用

二十一、什么时候用 WebClient?

适合:

  • 高并发
  • 网关
  • 响应式系统
  • 大量IO请求

二十二、企业里真实情况

很多公司:

text 复制代码
老项目:RestTemplate
新项目:OpenFeign/WebClient

因为:

text 复制代码
Feign 更适合微服务

例如:

java 复制代码
@FeignClient("user-service")
public interface UserClient {

    @GetMapping("/user/{id}")
    User get(@PathVariable Long id);
}

比 RestTemplate 更方便。


二十三、学习路线

建议学习顺序:

text 复制代码
1. HTTP基础
2. RestTemplate
3. HttpClient
4. OpenFeign
5. WebClient

因为:

text 复制代码
RestTemplate 是理解微服务调用最好的入门

二十四、一个完整实际案例

java 复制代码
@Service
public class UserService {

    @Autowired
    private RestTemplate restTemplate;

    public User getUser(Long id) {

        String url =
                "http://localhost:8080/user/{id}";

        HttpHeaders headers = new HttpHeaders();

        headers.add("token", "abc123");

        HttpEntity<Void> entity =
                new HttpEntity<>(headers);

        ResponseEntity<User> response =
                restTemplate.exchange(
                        url,
                        HttpMethod.GET,
                        entity,
                        User.class,
                        id
                );

        return response.getBody();
    }
}
相关推荐
Roselind_Yi8 小时前
池化对比:CNN池化 VS Java线程池
java·人工智能·经验分享·笔记·深度学习·神经网络·cnn
lizhongxuan11 小时前
AIOPS 的自治运维与可验证进化机制
后端
Warson_L15 小时前
python - set/tuple/dict quiz
后端
IT_Octopus15 小时前
Spring Boot 实战:@PostConstruct + Caffeine 缓存初始化与定时刷新
spring boot·后端·缓存
swipe16 小时前
从本地开发到生产部署:用 Docker Compose 跑通 NestJS、MySQL 与 Milvus
后端·langchain·llm
码事漫谈16 小时前
SenseNova Skills Studio:为商汤SenseNova U1打造的本地办公技能包
后端
zhangxingchao16 小时前
AI应用开发七:可以替代 RAG 的技术
前端·人工智能·后端
Java面试题总结16 小时前
java高频面试题(2026最新)
java·开发语言·jvm·数据库·spring·缓存
苦逼的猿宝17 小时前
学生心理咨询评估系统
java·毕业设计·springboot·计算机毕业设计