此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.1.10! |
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.1.10! |
Spring Framework 提供了以下用于调用 REST 端点的选择:
-
WebClient
- 具有流畅 API 的非阻塞、反应式客户端. -
RestTemplate
- 具有模板方法 API 的同步客户端。 -
HTTP 接口 - 带有生成的动态代理实现的带注释的接口。
WebClient
WebClient
是用于执行 HTTP 请求的非阻塞反应式客户端。它是
在 5.0 中引入,并提供了 的替代方案,支持
同步、异步和流式处理方案。RestTemplate
WebClient
支持以下功能:
-
非阻塞 I/O。
-
反应流背压。
-
高并发,硬件资源更少。
-
利用 Java 8 lambda 的函数式流畅 API。
-
同步和异步交互。
-
向上流式传输到服务器或从服务器流式传输。
有关详细信息,请参阅 WebClient。
RestTemplate
它提供了基于 HTTP 客户端库的更高级别的 API。它做到了
在一行中轻松调用 REST 端点。它公开了以下几组
重载方法:RestTemplate
RestTemplate 处于维护模式,仅请求次要
要接受的更改和错误。请考虑改用 WebClient。 |
方法组 | 描述 |
---|---|
|
通过 GET 检索表示。 |
|
使用 GET 检索 (即 status、headers 和 body)。 |
|
使用 HEAD 检索资源的所有标头。 |
|
使用 POST 创建新资源,并从响应中返回标头。 |
|
使用 POST 创建新资源,并从响应中返回表示形式。 |
|
使用 POST 创建新资源,并从响应中返回表示形式。 |
|
使用 PUT 创建或更新资源。 |
|
使用 PATCH 更新资源,并从响应中返回表示形式。
请注意,JDK 不支持 ,但 Apache
HttpComponents 和其他组件可以。 |
|
使用 DELETE 删除指定 URI 处的资源。 |
|
使用 ALLOW 检索资源允许的 HTTP 方法。 |
|
上述方法的更通用(且不那么固执己见)版本提供了额外的
需要时的灵活性。它接受(包括 HTTP 方法、URL、标头、
和 body 作为输入)并返回 . 这些方法允许使用 而不是指定
具有泛型的响应类型。 |
|
执行请求的最通用方式,可完全控制请求 通过回调接口进行准备和响应提取。 |
初始化
默认构造函数用于执行请求。您可以
切换到实现为 .
目前,还内置了对 Apache HttpComponents 和 OkHttp 的支持。java.net.HttpURLConnection
ClientHttpRequestFactory
例如,若要切换到 Apache HttpComponents,可以使用以下命令:
RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
每个都公开特定于基础的配置选项
HTTP 客户端库 — 例如,用于凭据、连接池和其他详细信息。ClientHttpRequestFactory
请注意,HTTP 请求的实现可能会在以下情况下引发异常
访问表示错误的响应(如 401)的状态。如果这是一个
问题,切换到另一个 HTTP 客户端库。java.net |
RestTemplate 可以检测可观察性,以生成指标和跟踪。
请参阅 RestTemplate 可观测性支持部分。 |
URI
许多方法接受 URI 模板和 URI 模板变量,
要么作为变量参数,要么作为 .RestTemplate
String
Map<String,String>
下面的示例使用变量参数:String
String result = restTemplate.getForObject(
"https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");
以下示例使用:Map<String, String>
Map<String, String> vars = Collections.singletonMap("hotel", "42");
String result = restTemplate.getForObject(
"https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
请记住,URI 模板是自动编码的,如以下示例所示:
restTemplate.getForObject("https://example.com/hotel list", String.class);
// Results in request to "https://example.com/hotel%20list"
可以使用 的属性自定义 URI
被编码。或者,您可以准备一个并将其传递给以下之一
接受 .uriTemplateHandler
RestTemplate
java.net.URI
RestTemplate
URI
有关使用 URI 和编码 URI 的更多详细信息,请参阅 URI 链接。
头
您可以使用这些方法来指定请求标头,如以下示例所示:exchange()
String uriTemplate = "https://example.com/hotels/{hotel}";
URI uri = UriComponentsBuilder.fromUriString(uriTemplate).build(42);
RequestEntity<Void> requestEntity = RequestEntity.get(uri)
.header("MyRequestHeader", "MyValue")
.build();
ResponseEntity<String> response = template.exchange(requestEntity, String.class);
String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
String body = response.getBody();
您可以通过返回 的许多方法变体来获取响应标头。RestTemplate
ResponseEntity
身体
传入方法和从方法返回的对象将转换为原始对象和从原始方法返回的对象
内容在 .RestTemplate
HttpMessageConverter
在 POST 上,输入对象序列化到请求正文,如以下示例所示:
URI location = template.postForLocation("https://example.com/people", person);
无需显式设置请求的 Content-Type 标头。在大多数情况下,
您可以根据源类型和所选内容找到兼容的消息转换器
消息转换器相应地设置内容类型。如有必要,可以使用这些方法显式提供请求标头,并且
转,影响选择的消息转换器。Object
exchange
Content-Type
在 GET 上,响应的主体被反序列化为输出,如以下示例所示:Object
Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42);
不需要显式设置请求的标头。在大多数情况下,
可以根据预期的响应类型找到兼容的消息转换器,该响应类型
然后帮助填充标头。如有必要,可以使用这些方法显式提供标头。Accept
Accept
exchange
Accept
默认情况下,注册所有内置消息转换器,具体取决于有助于的类路径检查
以确定存在哪些可选转换库。您还可以设置消息
要显式使用的转换器。RestTemplate
消息转换
该模块包含用于读取和
通过 和 写入 HTTP 请求和响应的正文。 实例用于客户端(例如,在 和
在服务器端(例如,在Spring MVC REST控制器中)。spring-web
HttpMessageConverter
InputStream
OutputStream
HttpMessageConverter
RestTemplate
框架中提供了主媒体 (MIME) 类型的具体实现
默认情况下,在客户端和服务器端注册(请参阅配置消息转换器)。RestTemplate
RequestMappingHandlerAdapter
以下各节介绍了 的实现。
对于所有转换器,都使用默认媒体类型,但可以通过设置 bean 属性来覆盖它。下表描述了每个实现:HttpMessageConverter
supportedMediaTypes
消息转换器 | 描述 |
---|---|
|
可以从 HTTP 读取和写入实例的实现
请求和响应。默认情况下,此转换器支持所有文本媒体类型
() 并用 的 写入 。 |
|
可以从 HTTP 读取和写入表单数据的实现
请求和响应。默认情况下,此转换器读取和写入媒体类型。表单数据从 .转换器还可以写入(但不能读取)分段
从 .默认情况下,是
支持。从 Spring Framework 5.2 开始,可以支持其他多部分子类型
写入表单数据。有关更多详细信息,请参阅 javadoc。 |
|
可以从
HTTP 请求和响应。默认情况下,此转换器支持所有媒体类型 ()
并用 的 写入 。您可以覆盖此内容
通过设置属性并覆盖 . |
|
一个可以通过使用 Spring 和包中的抽象来读取和写入 XML 的实现。
此转换器在使用之前需要 and。你可以注入这些
通过构造函数或 Bean 属性。默认情况下,此转换器支持 和 。 |
|
可以使用 Jackson 的 .您可以根据需要通过使用 Jackson 的
提供了注释。当您需要进一步控制时(对于自定义 JSON 的情况
需要为特定类型提供序列化程序/反序列化程序),可以通过属性注入自定义。默认情况下,这
转换器支持 . |
|
可以使用 Jackson XML 扩展的 .您可以使用 JAXB 根据需要定制 XML 映射
或杰克逊提供的注释。当需要进一步控制时(对于自定义 XML 的情况
需要为特定类型提供序列化程序/反序列化程序),可以通过属性注入自定义。默认情况下,这
转换器支持 . |
|
可以从 HTTP 请求和响应读取和写入的实现。仅支持 、 和 。默认情况下,此转换器支持 和 。 |
|
可以从 HTTP 请求和响应读取和写入的实现。此转换器读取
并写入 Java I/O API 支持的媒体类型。 |
Jackson JSON 视图
您可以指定 Jackson JSON 视图以仅序列化对象属性的子集,如以下示例所示:
MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23"));
value.setSerializationView(User.WithoutPasswordView.class);
RequestEntity<MappingJacksonValue> requestEntity =
RequestEntity.post(new URI("https://example.com/user")).body(value);
ResponseEntity<String> response = template.exchange(requestEntity, String.class);
多部分
若要发送分段数据,需要提供 who 值
可以是 for 部件内容、for 文件部件或 for
带有标题的部分内容。例如:MultiValueMap<String, Object>
Object
Resource
HttpEntity
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>();
parts.add("fieldPart", "fieldValue");
parts.add("filePart", new FileSystemResource("...logo.png"));
parts.add("jsonPart", new Person("Jason"));
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_XML);
parts.add("xmlPart", new HttpEntity<>(myBean, headers));
在大多数情况下,您不必为每个部件指定 。内容
类型根据所选的序列化自动确定
它或,在基于文件扩展名的情况下。如有必要,您可以
显式提供包装器。Content-Type
HttpMessageConverter
Resource
MediaType
HttpEntity
准备就绪后,您可以将其传递给 ,如下所示:MultiValueMap
RestTemplate
MultiValueMap<String, Object> parts = ...;
template.postForObject("https://example.com/upload", parts, Void.class);
如果 包含至少一个非值,则将
到 .如果 has 值 ,则默认为 。
如有必要,也可以显式设置。MultiValueMap
String
Content-Type
multipart/form-data
FormHttpMessageConverter
MultiValueMap
String
Content-Type
application/x-www-form-urlencoded
Content-Type
RestTemplate 处于维护模式,仅请求次要
要接受的更改和错误。请考虑改用 WebClient。 |
方法组 | 描述 |
---|---|
|
通过 GET 检索表示。 |
|
使用 GET 检索 (即 status、headers 和 body)。 |
|
使用 HEAD 检索资源的所有标头。 |
|
使用 POST 创建新资源,并从响应中返回标头。 |
|
使用 POST 创建新资源,并从响应中返回表示形式。 |
|
使用 POST 创建新资源,并从响应中返回表示形式。 |
|
使用 PUT 创建或更新资源。 |
|
使用 PATCH 更新资源,并从响应中返回表示形式。
请注意,JDK 不支持 ,但 Apache
HttpComponents 和其他组件可以。 |
|
使用 DELETE 删除指定 URI 处的资源。 |
|
使用 ALLOW 检索资源允许的 HTTP 方法。 |
|
上述方法的更通用(且不那么固执己见)版本提供了额外的
需要时的灵活性。它接受(包括 HTTP 方法、URL、标头、
和 body 作为输入)并返回 . 这些方法允许使用 而不是指定
具有泛型的响应类型。 |
|
执行请求的最通用方式,可完全控制请求 通过回调接口进行准备和响应提取。 |
请注意,HTTP 请求的实现可能会在以下情况下引发异常
访问表示错误的响应(如 401)的状态。如果这是一个
问题,切换到另一个 HTTP 客户端库。java.net |
RestTemplate 可以检测可观察性,以生成指标和跟踪。
请参阅 RestTemplate 可观测性支持部分。 |
消息转换器 | 描述 |
---|---|
|
可以从 HTTP 读取和写入实例的实现
请求和响应。默认情况下,此转换器支持所有文本媒体类型
() 并用 的 写入 。 |
|
可以从 HTTP 读取和写入表单数据的实现
请求和响应。默认情况下,此转换器读取和写入媒体类型。表单数据从 .转换器还可以写入(但不能读取)分段
从 .默认情况下,是
支持。从 Spring Framework 5.2 开始,可以支持其他多部分子类型
写入表单数据。有关更多详细信息,请参阅 javadoc。 |
|
可以从
HTTP 请求和响应。默认情况下,此转换器支持所有媒体类型 ()
并用 的 写入 。您可以覆盖此内容
通过设置属性并覆盖 . |
|
一个可以通过使用 Spring 和包中的抽象来读取和写入 XML 的实现。
此转换器在使用之前需要 and。你可以注入这些
通过构造函数或 Bean 属性。默认情况下,此转换器支持 和 。 |
|
可以使用 Jackson 的 .您可以根据需要通过使用 Jackson 的
提供了注释。当您需要进一步控制时(对于自定义 JSON 的情况
需要为特定类型提供序列化程序/反序列化程序),可以通过属性注入自定义。默认情况下,这
转换器支持 . |
|
可以使用 Jackson XML 扩展的 .您可以使用 JAXB 根据需要定制 XML 映射
或杰克逊提供的注释。当需要进一步控制时(对于自定义 XML 的情况
需要为特定类型提供序列化程序/反序列化程序),可以通过属性注入自定义。默认情况下,这
转换器支持 . |
|
可以从 HTTP 请求和响应读取和写入的实现。仅支持 、 和 。默认情况下,此转换器支持 和 。 |
|
可以从 HTTP 请求和响应读取和写入的实现。此转换器读取
并写入 Java I/O API 支持的媒体类型。 |
HTTP 接口
Spring Framework 允许您将 HTTP 服务定义为带有注释的 Java 接口 HTTP 交换的方法。然后,您可以生成实现此接口的代理 并执行交换。这有助于简化 HTTP 远程访问,这通常 涉及包装使用底层 HTTP 客户端的详细信息的外观。
一、声明一个带有方法的接口:@HttpExchange
interface RepositoryService {
@GetExchange("/repos/{owner}/{repo}")
Repository getRepository(@PathVariable String owner, @PathVariable String repo);
// more HTTP exchange methods...
}
第二,创建一个代理来执行声明的 HTTP 交换:
WebClient client = WebClient.builder().baseUrl("https://api.github.com/").build();
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
RepositoryService service = factory.createClient(RepositoryService.class);
@HttpExchange
在适用于所有方法的类型级别受支持:
@HttpExchange(url = "/repos/{owner}/{repo}", accept = "application/vnd.github.v3+json")
interface RepositoryService {
@GetExchange
Repository getRepository(@PathVariable String owner, @PathVariable String repo);
@PatchExchange(contentType = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
void updateRepository(@PathVariable String owner, @PathVariable String repo,
@RequestParam String name, @RequestParam String description, @RequestParam String homepage);
}
方法参数
带注释的 HTTP 交换方法支持灵活的方法签名,具有以下功能 方法参数:
方法参数 | 描述 |
---|---|
|
动态设置请求的 URL,覆盖注释的属性。 |
|
动态设置请求的 HTTP 方法,覆盖注释的属性 |
|
添加一个或多个请求标头。参数可以是具有多个标头的 或、值的 或
个人价值。非 String 值支持类型转换。 |
|
添加一个变量,以便在请求 URL 中展开占位符。参数可以是具有多个变量的 a,也可以是单个值。类型转换
支持非 String 值。 |
|
提供请求的正文作为要序列化的对象,或
支持的反应式流(如 、 或任何其他异步类型)
通过配置的 . |
|
添加一个或多个请求参数。参数可以是具有多个参数的 a、值的 a 或
单个值。非 String 值支持类型转换。 当设置为 时,请求
参数在请求正文中编码。否则,它们将添加为 URL 查询
参数。 |
|
添加请求部分,可以是 String(表单字段)、(文件部分)、
对象(要编码的实体,例如 JSON)、(部分内容和标头)、
弹簧,或上述任何一种的反应流。 |
|
添加一个或多个 Cookie。参数可以是具有多个 cookie 的 或、值的 或
个人价值。非 String 值支持类型转换。 |
返回值
带注释的 HTTP 交换方法支持以下返回值:
方法返回值 | 描述 |
---|---|
|
执行给定的请求,并发布响应内容(如果有)。 |
|
执行给定的请求,释放响应内容(如果有),然后返回 响应标头。 |
|
执行给定的请求,并将响应内容解码为声明的返回类型。 |
|
执行给定的请求并将响应内容解码为声明的流 元素类型。 |
|
执行给定的请求,并释放响应内容(如果有),并返回带有状态和标头的 a。 |
|
执行给定的请求,将响应内容解码为声明的返回类型,然后
返回 A 以及状态、标头和解码正文。 |
|
执行给定的请求,将响应内容解码为声明的流
元素类型,并返回 A 与状态、标头和解码
响应正文流。 |
您还可以使用在 中注册的任何其他异步或反应式类型。ReactiveAdapterRegistry |
异常处理
默认情况下,引发 4xx 和 5xx HTTP 状态
代码。若要自定义此项,可以注册一个适用于所有
通过客户端执行的响应:WebClient
WebClientResponseException
WebClient webClient = WebClient.builder()
.defaultStatusHandler(HttpStatusCode::isError, resp -> ...)
.build();
WebClientAdapter clientAdapter = WebClientAdapter.forClient(webClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory
.builder(clientAdapter).build();
有关更多详细信息和选项,例如禁止显示错误状态代码,请参阅 in 的 Javadoc。defaultStatusHandler
WebClient.Builder
方法参数 | 描述 |
---|---|
|
动态设置请求的 URL,覆盖注释的属性。 |
|
动态设置请求的 HTTP 方法,覆盖注释的属性 |
|
添加一个或多个请求标头。参数可以是具有多个标头的 或、值的 或
个人价值。非 String 值支持类型转换。 |
|
添加一个变量,以便在请求 URL 中展开占位符。参数可以是具有多个变量的 a,也可以是单个值。类型转换
支持非 String 值。 |
|
提供请求的正文作为要序列化的对象,或
支持的反应式流(如 、 或任何其他异步类型)
通过配置的 . |
|
添加一个或多个请求参数。参数可以是具有多个参数的 a、值的 a 或
单个值。非 String 值支持类型转换。 当设置为 时,请求
参数在请求正文中编码。否则,它们将添加为 URL 查询
参数。 |
|
添加请求部分,可以是 String(表单字段)、(文件部分)、
对象(要编码的实体,例如 JSON)、(部分内容和标头)、
弹簧,或上述任何一种的反应流。 |
|
添加一个或多个 Cookie。参数可以是具有多个 cookie 的 或、值的 或
个人价值。非 String 值支持类型转换。 |
方法返回值 | 描述 |
---|---|
|
执行给定的请求,并发布响应内容(如果有)。 |
|
执行给定的请求,释放响应内容(如果有),然后返回 响应标头。 |
|
执行给定的请求,并将响应内容解码为声明的返回类型。 |
|
执行给定的请求并将响应内容解码为声明的流 元素类型。 |
|
执行给定的请求,并释放响应内容(如果有),并返回带有状态和标头的 a。 |
|
执行给定的请求,将响应内容解码为声明的返回类型,然后
返回 A 以及状态、标头和解码正文。 |
|
执行给定的请求,将响应内容解码为声明的流
元素类型,并返回 A 与状态、标头和解码
响应正文流。 |
您还可以使用在 中注册的任何其他异步或反应式类型。ReactiveAdapterRegistry |