|
对于最新稳定版本,请使用Spring Framework 7.0.1! |
REST 客户端
Web客户端
Web客户端是一个非阻塞、被动的客户端,用于执行HTTP请求。确实如此
该系统在5.0中引入,提供了Rest模板,支持
同步、异步和流式场景。
Web客户端支持以下内容:
-
非阻塞输入输出。
-
反应流带来背压。
-
高并发,硬件资源更少。
-
功能式、流畅的API,充分利用Java 8 lambda。
-
同步与异步交互。
-
可以从服务器上流式传输,也可以从服务器式传输。
详情请参见WebClient。
Rest模板
这Rest模板通过 HTTP 客户端库提供更高级的 API。它能做到
只需一行即可调用 REST 端点。它揭示了以下几类
超载方法:
Rest模板处于维护状态,仅对小请求
需要接受的变更和漏洞。请考虑使用WebClient。 |
| 方法组 | 描述 |
|---|---|
|
通过GET检索表示。 |
|
检索 |
|
通过使用 HEAD 检索资源的所有头部。 |
|
通过使用 POST 创建新资源并返回 |
|
通过POST创建新资源,返回响应中的表示。 |
|
通过POST创建新资源,返回响应中的表示。 |
|
通过PUT创建或更新资源。 |
|
通过PATCH更新资源,并返回响应中的表示。注意 JDK |
|
通过使用 DELETE 删除指定 URI 处的资源。 |
|
通过使用 ALLOW 检索资源允许的 HTTP 方法。 |
|
对前述方法更为通用(且观点更少)的版本,在需要时提供额外的灵活性。它接受 这些方法允许使用 |
|
执行请求的最通用方式,完全控制请求通过回调接口进行准备和响应提取。 |
初始化
默认构造函数使用java.net.HttpURLConnection执行请求。 您可以 切换到另一个HTTP库,实现为ClientHttpRequestFactory. 目前,App HttpComponents 和 OkHttp 也内置支持。
例如,要切换到 Apache HttpComponents,可以使用以下工具:
RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
每ClientHttpRequestFactory暴露针对底层HTTP 客户端库的配置选项——例如,用于凭证、连接池及其他细节。
注意java.netHTTP请求的实现可以在访问代表错误的响应状态(例如401)时触发异常。如果这是问题,切换到另一个HTTP客户端库。 |
Rest模板可以对可观测性进行仪器化,以产生度量和跟踪。参见 RestTemplate 可观测性支持部分。 |
上岛信息大学
许多Rest模板方法接受URI模板和URI模板变量,作为字符串变量参数,或地图<字符串,字符串>.
以下示例使用了一个字符串变量参数:
String result = restTemplate.getForObject(
"https://example.com/hotels/{hotel}/bookings/{booking}", String.class, "42", "21");
以下示例使用了一个映射<字符串,字符串>:
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"
你可以使用uriTemplateHandler的属性Rest模板以自定义URIs的编码方式。或者,你可以准备一个java.net.URI并传入其中一个 这Rest模板接受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();
你可以通过多种方式获得响应头Rest模板返回的方法变体响应实体.
身体
物体进出又返回Rest模板方法通过HttpMessage转换器.
在POST中,输入对象被序列化到请求体,如下示例所示:
URI location = template.postForLocation("https://example.com/people", person);
你不必明确设置请求的内容类型头部。在大多数情况下,你可以根据源找到兼容的消息转换器对象类型,以及所选消息转换器相应地设置内容类型。如有必要,您可以使用交换用来显式提供内容类型请求头部,而这反过来会影响选择的消息转换器。
在GET中,响应的主体被反序列化为输出对象,如下示例所示:
Person person = restTemplate.getForObject("https://example.com/people/{id}", Person.class, 42);
这接受请求的头部不需要显式设置。在大多数情况下,可以根据预期的响应类型找到兼容的消息转换器,该类型然后有助于填充接受页眉。 如果有必要,你可以使用交换提供接受明确表示。
默认情况下,Rest模板注册所有内置的消息转换器,依赖于帮助确定有哪些可选的转换库。您也可以设置消息转换为显式使用。
消息转换
这春网模包含HttpMessage转换器阅读合同和
通过输入流和输出流.HttpMessage转换器实例在客户端使用(例如,在Rest模板)
服务器端(例如,在 Spring MVC REST 控制器中)。
框架中提供了主媒体(MIME)类型的具体实现
并且默认情况下,会注册于Rest模板客户端和RequestMappingHandlerAdapter服务器端(参见配置消息转换器)。
的实现HttpMessage转换器以下章节将有详细描述。
所有转换器都使用默认的媒体类型,但你可以通过设置支持媒体类型豆子的财产。下表描述了每种实现:
| 消息转换器 | 描述 |
|---|---|
|
一 |
|
一 |
|
一 |
|
一 |
|
一 |
|
一 |
|
一 |
|
一 |
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);
多部分
要发送多部分数据,你需要提供MultiValueMap <String, Object>其值
可能是对象部分内容为资源对于銼部分,或Http实体为
部分内容包含标题。例如:
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));
在大多数情况下,你不必特别说明内容类型每个部分。内容
类型是根据HttpMessage转换器被选为连载
它或,在 a 的情况下资源基于文件扩展名。如果有必要,你可以
明确提供媒体类型带有Http实体包装纸。
一旦多价值地图准备好了,你可以传给Rest模板,如下所示:
MultiValueMap<String, Object> parts = ...;
template.postForObject("https://example.com/upload", parts, Void.class);
如果多价值地图至少包含一个非字符串值,该内容类型是设定的
自多部分/形式-数据由FormHttpMessage转换器.如果多价值地图具有字符串值内容类型默认为application/x-www-form-urlencoded.
如有必要内容类型也可以明确设置。
HTTP 接口
Spring 框架允许你将 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方法,覆盖注释的 |
|
添加一个请求头或多个头部。该论证可能是 |
|
在请求URL中添加一个变量,用于展开占位符。该论证可能是 |
|
提供请求的正文,可以作为一个待序列化的对象,或者
反应流 |
|
添加请求参数或多个参数。该论证可能是 什么时候 |
|
添加请求部分,可以是字符串(表单字段), |
|
添加一个或多个 Cookie。该论证可能是 |
回报值
带注释的 HTTP 交换方法支持以下返回值:
| 方法返回值 | 描述 |
|---|---|
|
执行给定的请求,并发布响应内容(如有)。 |
|
执行给定请求,释放响应内容(如有),并返回 响应头。 |
|
执行给定请求,并将响应内容解码为声明的返回类型。 |
|
执行给定请求,并将响应内容解码到声明的流中 元素类型。 |
|
执行给定请求,释放响应内容(如有),返回 |
|
执行给定请求,将响应内容解码为声明的返回类型,然后
返回A |
|
执行给定请求,解码声明流的响应内容
元素类型,返回 |
你也可以使用注册在ReactiveAdapter注册表. |
异常处理
默认情况下,Web客户端提高WebClientResponseException用于4xx和5xx的HTTP状态
代码。为了自定义,你可以注册一个响应状态处理程序,适用于所有
通过客户端执行的响应:
WebClient webClient = WebClient.builder()
.defaultStatusHandler(HttpStatusCode::isError, resp -> ...)
.build();
WebClientAdapter clientAdapter = WebClientAdapter.forClient(webClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory
.builder(clientAdapter).build();
关于更多细节和选项,如抑制错误状态码,请参见 的 JavadocdefaultStatusHandler在WebClient.Builder.