首页 / Spring Boot 入门教程 / 调用 REST 服务

Spring Boot 入门教程

调用 REST 服务

本教程共 48 篇 · 第 22 篇 · 更新于 2026-08-13 · 约 3 分钟阅读

Spring BootRestClientWebClientRestTemplateHTTP 客户端REST 调用

本节目标:学会用 RestClient 调用远程接口,看懂 WebClient 的响应式写法,知道 RestTemplate 为什么退居二线。

三种客户端怎么选

Spring 家族给了三个 HTTP 客户端,别纠结,先记结论:

客户端风格定位
RestClient命令式,链式 API4.x 主线选择
WebClient响应式,返回 Mono/FluxWebFlux 项目用
RestTemplate命令式,老 API已弃用,只维护存量代码

普通 Spring MVC 项目,调远程接口默认选 RestClient。它和 RestTemplate 一样是同步阻塞的,但 API 更现代,好读好写。

RestClient 基础用法

Spring Boot 自动配置了一个 RestClient.Builder,直接注入使用:

package com.example.demo.service;

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;

@Service
public class ProductClient {

    private final RestClient restClient;

    public ProductClient(RestClient.Builder builder) {
        // baseUrl 定根地址,后面只写相对路径
        this.restClient = builder.baseUrl("https://api.example.com").build();
    }

    public String findById(Long id) {
        return restClient.get()
                .uri("/products/{id}", id)
                .retrieve()
                .body(String.class);
    }
}

链式调用三段式:发起方法(get/post)→ 请求配置(uri/header/body)→ 接收结果(retrieve)。

URI 里的 {id} 是占位符,后面的参数按顺序填充,不用手拼字符串。

调 JSON 接口并转对象

远程接口返回 JSON 时,body() 直接收对象或集合。需要一个配套的模型类:

package com.example.demo.model;

public class Product {

    private Long id;
    private String name;
    private Double price;

    // getter / setter 省略
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public Double getPrice() { return price; }
    public void setPrice(Double price) { this.price = price; }
}
package com.example.demo.service;

import java.util.List;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;

import com.example.demo.model.Product;

@Service
public class ProductClient {

    private final RestClient restClient;

    public ProductClient(RestClient.Builder builder) {
        this.restClient = builder.baseUrl("https://api.example.com").build();
    }

    // GET 查询单个
    public Product getProduct(Long id) {
        return restClient.get()
                .uri("/products/{id}", id)
                .retrieve()
                .body(Product.class);
    }

    // GET 查询列表
    public List<Product> listProducts() {
        return restClient.get()
                .uri("/products")
                .retrieve()
                .body(List.class);
    }

    // POST 提交 JSON
    public Product createProduct(Product product) {
        return restClient.post()
                .uri("/products")
                .contentType(MediaType.APPLICATION_JSON)
                .body(product)
                .retrieve()
                .body(Product.class);
    }

    // DELETE 无响应体
    public void deleteProduct(Long id) {
        restClient.delete()
                .uri("/products/{id}", id)
                .retrieve()
                .toBodilessEntity();
    }
}
Tip

body(List.class) 转集合时元素类型是 Object,需要时用 ParameterizedTypeReference 指定泛型,例如 body(new ParameterizedTypeReference<List<Product>>() {})

出错怎么办

远程返回 4xx/5xx 时,retrieve() 默认抛 RestClientResponseException 的子类。想精细处理,用 onStatus 拦截:

public Product getProduct(Long id) {
    return restClient.get()
            .uri("/products/{id}", id)
            .retrieve()
            .onStatus(
                    status -> status.value() == 404,
                    (request, response) -> {
                        throw new NotFoundException("商品不存在");
                    })
            .body(Product.class);
}

状态码符合条件就执行自定义逻辑,把远程错误翻译成本地业务异常。

WebClient:响应式调用

WebFlux 项目里用 WebClient。API 结构和 RestClient 很像,但返回的是响应式类型:

package com.example.demo.service;

import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;

import com.example.demo.model.Product;

import reactor.core.publisher.Mono;

@Service
public class ReactiveProductClient {

    private final WebClient webClient;

    public ReactiveProductClient(WebClient.Builder builder) {
        this.webClient = builder.baseUrl("https://api.example.com").build();
    }

    public Mono<Product> getProduct(Long id) {
        return webClient.get()
                .uri("/products/{id}", id)
                .retrieve()
                .bodyToMono(Product.class);
    }
}

调用方订阅 Mono 才真正发请求。在同步代码里想立刻拿结果,用 block()

Product product = client.getProduct(1L).block();
Note

WebClient 适合 WebFlux 响应式项目,Spring Boot 会按 classpath 自动选底层连接器(Reactor Netty、Jetty、JDK HttpClient)。MVC 项目用 RestClient 更简单。

RestTemplate:曾经的王者

RestTemplate 是 2009 年就有的老 API,统治了十多年。写法啰嗦,每个请求都要先包 HttpEntity

// 旧写法:RestTemplate(已弃用,仅对照)
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.getForEntity(
        "https://api.example.com/products/{id}", String.class, 1L);
String body = response.getBody();

Spring Framework 官方已将它标记为 deprecated,Spring Boot 4.x 不再提供自动配置的 RestTemplate 实例,只保留 RestTemplateBuilder 方便存量代码构建。

新代码别再用它。理由不只是弃用:API 冗长、错误处理要靠 try-catch 解析响应体、测试也不方便。RestClient 是它的现代替代品,迁移成本很低。

进阶:HTTP Service 接口

Spring 6 起支持声明式 HTTP 客户端:把远程接口定义成 Java 接口,注解描述请求,框架自动生成实现。适合服务之间调用,代码最简洁。

package com.example.demo.client;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.service.annotation.GetExchange;
import org.springframework.web.service.annotation.HttpExchange;

import com.example.demo.model.Product;

@HttpExchange(url = "https://api.example.com")
public interface ProductApi {

    @GetExchange("/products/{id}")
    Product getProduct(@PathVariable Long id);
}

在主类上注册扫描:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.service.registry.ImportHttpServices;

@SpringBootApplication
@ImportHttpServices(basePackages = "com.example.demo.client")
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

之后直接注入 ProductApi 调用,不用写实现类。

本节小结

  • MVC 项目调远程接口默认 RestClient,注入自动配置的 Builder。
  • WebFlux 项目用 WebClient,响应式 API,需要时 block() 取结果。
  • RestTemplate 已弃用,新代码不写,存量代码用 RestTemplateBuilder 维护。
  • HTTP Service 接口用注解描述请求,适合服务间调用。