对于最新的稳定版本,请使用 Spring Framework 6.2.0spring-doc.cadn.net.cn

REST 客户端

Spring 框架提供了以下选项来调用 REST 端点:spring-doc.cadn.net.cn

WebClient

WebClient是执行 HTTP 请求的非阻塞反应式客户端。它是 在 5.0 中引入,并提供了RestTemplate,支持 同步、异步和流式处理方案。spring-doc.cadn.net.cn

WebClient支持以下内容:spring-doc.cadn.net.cn

有关更多详细信息,请参阅 WebClientspring-doc.cadn.net.cn

RestTemplate

RestTemplate通过 HTTP 客户端库提供更高级别的 API。它使它 易于在单行中调用 REST 端点。它公开了以下几组 重载方法:spring-doc.cadn.net.cn

RestTemplate处于维护模式,仅请求次要 要接受的更改和错误。请考虑改用 WebClient
表 1.RestTemplate 方法
“方法”组 描述

getForObjectspring-doc.cadn.net.cn

通过 GET 检索表示形式。spring-doc.cadn.net.cn

getForEntityspring-doc.cadn.net.cn

检索ResponseEntity(即 status、headers 和 body)。spring-doc.cadn.net.cn

headForHeadersspring-doc.cadn.net.cn

使用 HEAD 检索资源的所有标头。spring-doc.cadn.net.cn

postForLocationspring-doc.cadn.net.cn

使用 POST 创建新资源并返回Location标头。spring-doc.cadn.net.cn

postForObjectspring-doc.cadn.net.cn

使用 POST 创建新资源,并从响应中返回表示形式。spring-doc.cadn.net.cn

postForEntityspring-doc.cadn.net.cn

使用 POST 创建新资源,并从响应中返回表示形式。spring-doc.cadn.net.cn

putspring-doc.cadn.net.cn

使用 PUT 创建或更新资源。spring-doc.cadn.net.cn

patchForObjectspring-doc.cadn.net.cn

使用 PATCH 更新资源并从响应中返回表示形式。 请注意,JDKHttpURLConnection不支持PATCH,但 Apache HttpComponents 和其他组件可以。spring-doc.cadn.net.cn

deletespring-doc.cadn.net.cn

使用 DELETE 删除指定 URI 处的资源。spring-doc.cadn.net.cn

optionsForAllowspring-doc.cadn.net.cn

使用 ALLOW 检索资源允许的 HTTP 方法。spring-doc.cadn.net.cn

exchangespring-doc.cadn.net.cn

上述方法的更通用(且不那么固执己见)版本,它提供额外的 需要时灵活。它接受一个RequestEntity(包括 HTTP 方法、URL、标头、 和 body 作为输入)并返回一个ResponseEntity.spring-doc.cadn.net.cn

这些方法允许使用ParameterizedTypeReference而不是Class以指定 具有泛型的响应类型。spring-doc.cadn.net.cn

executespring-doc.cadn.net.cn

执行请求的最通用方式,可完全控制请求 通过回调接口进行准备和响应提取。spring-doc.cadn.net.cn

初始化

默认构造函数使用java.net.HttpURLConnection执行请求。您可以 切换到其他 HTTP 库,并使用ClientHttpRequestFactory. 目前,还内置了对 Apache HttpComponents 和 OkHttp 的支持。spring-doc.cadn.net.cn

例如,要切换到 Apache HttpComponents,您可以使用以下内容:spring-doc.cadn.net.cn

RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());

ClientHttpRequestFactory公开特定于底层的配置选项 HTTP 客户端库 — 例如,用于凭证、连接池和其他详细信息。spring-doc.cadn.net.cn

请注意,java.netHTTP 请求的实现可能会引发异常 访问表示错误的响应的状态(如 401)。如果这是一个 问题,请切换到另一个 HTTP 客户端库。
RestTemplate可以进行检测以实现可观测性,以便生成指标和跟踪。 请参阅 RestTemplate 可观察性支持部分。

URI

许多RestTemplate方法接受 URI 模板和 URI 模板变量, 要么作为Stringvariable 参数或Map<String,String>.spring-doc.cadn.net.cn

以下示例使用Stringvariable 参数:spring-doc.cadn.net.cn

String result = restTemplate.getForObject(
		"https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");

以下示例使用Map<String, String>:spring-doc.cadn.net.cn

Map<String, String> vars = Collections.singletonMap("hotel", "42");

String result = restTemplate.getForObject(
		"https://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);

请记住,URI 模板是自动编码的,如下例所示:spring-doc.cadn.net.cn

restTemplate.getForObject("https://example.com/hotel list", String.class);

// Results in request to "https://example.com/hotel%20list"

您可以使用uriTemplateHandler的属性RestTemplate自定义 URI 的方式 进行编码。或者,您可以准备一个java.net.URI并将其传递到 这RestTemplate方法,该方法接受URI.spring-doc.cadn.net.cn

有关使用 URI 和编码 URI 的更多详细信息,请参阅 URI 链接spring-doc.cadn.net.cn

您可以使用exchange()方法指定请求标头,如下例所示:spring-doc.cadn.net.cn

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();

您可以通过许多RestTemplatemethod 变体,返回ResponseEntity.spring-doc.cadn.net.cn

身体

传入和返回的对象RestTemplate方法与 Raw 相互转换 content 在HttpMessageConverter.spring-doc.cadn.net.cn

在 POST 上,输入对象将序列化为请求正文,如下例所示:spring-doc.cadn.net.cn

URI location = template.postForLocation("https://example.com/people", person);

您无需显式设置请求的 Content-Type 标头。在大多数情况下, 您可以根据来源找到兼容的消息转换器Objecttype 和所选的 Message Converter 会相应地设置内容类型。如有必要,您可以使用exchange方法显式提供Content-Typerequest 标头,并且 turn 影响选择的消息转换器。spring-doc.cadn.net.cn

在 GET 上,响应的主体被反序列化为输出Object,如下例所示:spring-doc.cadn.net.cn

Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42);

Acceptheader 不需要显式设置。在大多数情况下, 可以根据预期的响应类型找到兼容的消息转换器,该 然后帮助填充Accept页眉。如有必要,您可以使用exchange方法提供Accept标头。spring-doc.cadn.net.cn

默认情况下,RestTemplate注册所有内置消息转换器,具体取决于 Classpath 检查,这有助于 来确定存在哪些可选的转换库。您还可以设置消息 转换器来显式使用。spring-doc.cadn.net.cn

消息转换

spring-webmodule 包含HttpMessageConverterContract 进行读取和 通过InputStreamOutputStream.HttpMessageConverter实例在客户端使用(例如,在RestTemplate) 和 在服务器端(例如,在 Spring MVC REST 控制器中)。spring-doc.cadn.net.cn

框架中提供了主媒体 (MIME) 类型的具体实现 ,默认情况下,它们已注册到RestTemplate在客户端,使用RequestMappingHandlerAdapter在服务器端(请参阅 配置消息转换器)。spring-doc.cadn.net.cn

HttpMessageConverter在以下各节中进行了介绍。 对于所有转换器,都使用默认媒体类型,但您可以通过设置supportedMediaTypesbean 属性。下表描述了每种实现:spring-doc.cadn.net.cn

表 2.HttpMessageConverter 实现
消息转换器 描述

StringHttpMessageConverterspring-doc.cadn.net.cn

HttpMessageConverter可以读写的实现String实例 请求和响应。默认情况下,此转换器支持所有文本媒体类型 (text/*) 并使用Content-Typetext/plain.spring-doc.cadn.net.cn

FormHttpMessageConverterspring-doc.cadn.net.cn

HttpMessageConverter可以从 HTTP 读取和写入表单数据的实现 请求和响应。默认情况下,此转换器读取和写入application/x-www-form-urlencodedmedia 类型。表单数据从MultiValueMap<String, String>.转换器还可以写入(但不能读取)multipart 从MultiValueMap<String, Object>.默认情况下,multipart/form-data是 支持。从 Spring Framework 5.2 开始,可以支持其他多部分子类型 写入表单数据。请参阅 javadoc 以获取FormHttpMessageConverter了解更多详情。spring-doc.cadn.net.cn

ByteArrayHttpMessageConverterspring-doc.cadn.net.cn

HttpMessageConverter可以从 HTTP 请求和响应。默认情况下,此转换器支持所有媒体类型 () 并使用*/*Content-Typeapplication/octet-stream.您可以覆盖此 通过设置supportedMediaTypesproperty 和 overridridinggetContentType(byte[]).spring-doc.cadn.net.cn

MarshallingHttpMessageConverterspring-doc.cadn.net.cn

HttpMessageConverter实现,该实现可以使用 Spring 的MarshallerUnmarshallerabstractions 的org.springframework.oxm包。 此转换器需要一个MarshallerUnmarshaller才能使用。您可以注入这些 通过 constructor 或 bean 属性。默认情况下,此转换器支持text/xmlapplication/xml.spring-doc.cadn.net.cn

MappingJackson2HttpMessageConverterspring-doc.cadn.net.cn

HttpMessageConverter可以使用 Jackson 的ObjectMapper.您可以根据需要使用 Jackson 的 提供的注释。当您需要进一步控制时(对于自定义 JSON 需要为特定类型提供序列化器/反序列化器),你可以注入一个自定义的ObjectMapper通过ObjectMapper财产。默认情况下,此 转换器支持application/json.spring-doc.cadn.net.cn

MappingJackson2XmlHttpMessageConverterspring-doc.cadn.net.cn

HttpMessageConverter可以使用 Jackson XML 扩展的XmlMapper.您可以根据需要通过使用 JAXB 来自定义 XML 映射 或 Jackson 提供的注释。当您需要进一步控制时(对于自定义 XML 需要为特定类型提供序列化器/反序列化器),你可以注入一个自定义的XmlMapper通过ObjectMapper财产。默认情况下,此 转换器支持application/xml.spring-doc.cadn.net.cn

SourceHttpMessageConverterspring-doc.cadn.net.cn

HttpMessageConverter可以读写的实现javax.xml.transform.Source从 HTTP 请求和响应。只DOMSource,SAXSourceStreamSource受支持。默认情况下,此转换器支持text/xmlapplication/xml.spring-doc.cadn.net.cn

BufferedImageHttpMessageConverterspring-doc.cadn.net.cn

HttpMessageConverter可以读写的实现java.awt.image.BufferedImage从 HTTP 请求和响应。此转换器读取 并写入 Java I/O API 支持的媒体类型。spring-doc.cadn.net.cn

Jackson JSON 视图

您可以指定 Jackson JSON 视图以仅序列化对象属性的子集,如下例所示:spring-doc.cadn.net.cn

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);

多部分

要发送多部分数据,您需要提供MultiValueMap<String, Object>其值 可能是Object对于部件内容,一个Resource对于文件部分,或者HttpEntity为 带有标题的 part 内容。例如:spring-doc.cadn.net.cn

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对于每个部分。内容 type 是根据HttpMessageConverter选择要序列化 it 或Resource基于文件扩展名。如有必要,您可以 显式提供MediaType替换为HttpEntity包装纸。spring-doc.cadn.net.cn

一旦MultiValueMap已准备就绪,您可以将其传递给RestTemplate,如下所示:spring-doc.cadn.net.cn

MultiValueMap<String, Object> parts = ...;
template.postForObject("https://example.com/upload", parts, Void.class);

如果MultiValueMap包含至少一个非String值、Content-Type已设置 自multipart/form-dataFormHttpMessageConverter.如果MultiValueMap具有StringContent-Type默认为application/x-www-form-urlencoded. 如有必要,Content-Type也可以显式设置。spring-doc.cadn.net.cn

HTTP 接口

Spring Framework 允许您将 HTTP 服务定义为带有注释的 Java 接口 方法进行 HTTP 交换。然后,您可以生成实现此接口的代理 并执行交换。这有助于简化 HTTP 远程访问,这通常 涉及一个 Facade,该 Facade 包装了使用底层 HTTP 客户端的详细信息。spring-doc.cadn.net.cn

一、使用@HttpExchange方法:spring-doc.cadn.net.cn

interface RepositoryService {

	@GetExchange("/repos/{owner}/{repo}")
	Repository getRepository(@PathVariable String owner, @PathVariable String repo);

	// more HTTP exchange methods...

}

第二,创建一个代理,该代理将执行声明的 HTTP 交换:spring-doc.cadn.net.cn

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在类型级别受支持,它适用于所有方法:spring-doc.cadn.net.cn

@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 交换方法支持灵活的方法签名,包括以下内容 方法参数:spring-doc.cadn.net.cn

Method 参数 描述

URIspring-doc.cadn.net.cn

动态设置请求的 URL,覆盖注释的url属性。spring-doc.cadn.net.cn

HttpMethodspring-doc.cadn.net.cn

动态设置请求的 HTTP 方法,覆盖注释的method属性spring-doc.cadn.net.cn

@RequestHeaderspring-doc.cadn.net.cn

添加一个或多个请求标头。参数可以是Map<String, ?>MultiValueMap<String, ?>对于多个标头,一个Collection<?>的值,或者 individual value 的非 String 值支持类型转换。spring-doc.cadn.net.cn

@PathVariablespring-doc.cadn.net.cn

在请求 URL 中添加用于扩展占位符的变量。参数可以是Map<String, ?>具有多个变量或单个值。类型转换 支持非 String 值。spring-doc.cadn.net.cn

@RequestBodyspring-doc.cadn.net.cn

将请求的主体作为要序列化的对象或 反应式流PublisherMono,Flux或任何其他异步类型支持的 通过配置的ReactiveAdapterRegistry.spring-doc.cadn.net.cn

@RequestParamspring-doc.cadn.net.cn

添加一个或多个请求参数。参数可以是Map<String, ?>MultiValueMap<String, ?>如果有多个参数,则Collection<?>of 值或 单个值。非 String 值支持类型转换。spring-doc.cadn.net.cn

什么时候"content-type"设置为"application/x-www-form-urlencoded"请求 参数在请求正文中编码。否则,它们将被添加为 URL 查询 参数。spring-doc.cadn.net.cn

@RequestPartspring-doc.cadn.net.cn

添加请求部分,可以是 String (表单字段),Resource(文件部分)、 对象(要编码的实体,例如作为 JSON)、HttpEntity(部分内容和标题)、 弹簧Part或 Reactive StreamsPublisher属于上述任何一项。spring-doc.cadn.net.cn

@CookieValuespring-doc.cadn.net.cn

添加一个或多个 Cookie。参数可以是Map<String, ?>MultiValueMap<String, ?>对于多个 Cookie,则Collection<?>的值,或者 individual value 的非 String 值支持类型转换。spring-doc.cadn.net.cn

返回值

带注释的 HTTP 交换方法支持以下返回值:spring-doc.cadn.net.cn

方法返回值 描述

void,Mono<Void>spring-doc.cadn.net.cn

执行给定的请求,并发布响应内容(如果有)。spring-doc.cadn.net.cn

HttpHeaders,Mono<HttpHeaders>spring-doc.cadn.net.cn

执行给定的请求,释放响应内容(如果有),并返回 响应标头。spring-doc.cadn.net.cn

<T>,Mono<T>spring-doc.cadn.net.cn

执行给定的请求并将响应内容解码为声明的返回类型。spring-doc.cadn.net.cn

<T>,Flux<T>spring-doc.cadn.net.cn

执行给定的请求,并将响应内容解码为声明的 元素类型。spring-doc.cadn.net.cn

ResponseEntity<Void>,Mono<ResponseEntity<Void>>spring-doc.cadn.net.cn

执行给定的请求,并释放响应内容(如果有),并返回一个ResponseEntity替换为 Status 和 Headers。spring-doc.cadn.net.cn

ResponseEntity<T>,Mono<ResponseEntity<T>>spring-doc.cadn.net.cn

执行给定的请求,将响应内容解码为声明的返回类型,然后 返回一个ResponseEntity替换为 status、Headers 和 Decoded body。spring-doc.cadn.net.cn

Mono<ResponseEntity<Flux<T>>spring-doc.cadn.net.cn

执行给定的请求,将响应内容解码为声明的 元素类型,并返回一个ResponseEntity替换为 status、headers 和 decoded 响应正文流。spring-doc.cadn.net.cn

您还可以使用在ReactiveAdapterRegistry.

异常处理

默认情况下,WebClient提高WebClientResponseException对于 4xx 和 5xx HTTP 状态 代码。要自定义此功能,您可以注册一个适用于所有 通过客户端执行的响应:spring-doc.cadn.net.cn

WebClient webClient = WebClient.builder()
		.defaultStatusHandler(HttpStatusCode::isError, resp -> ...)
		.build();

WebClientAdapter clientAdapter = WebClientAdapter.forClient(webClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory
		.builder(clientAdapter).build();

有关更多详细信息和选项(例如禁止显示错误状态代码),请参阅 JavadocdefaultStatusHandlerWebClient.Builder.spring-doc.cadn.net.cn