Spring 教程—REST 客户端详解(WebClient 、RestTemplate、HTTP 接口)

这篇具有很好参考价值的文章主要介绍了Spring 教程—REST 客户端详解(WebClient 、RestTemplate、HTTP 接口)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Spring框架为调用REST端点提供了以下选择:

  • WebClient - 非阻塞、响应式客户端和 fluent API。
  • RestTemplate - 带有模板方法API的同步客户端。
  • HTTP 接口 - 注解式接口,并生成动态代理实现。

一、 WebClient

WebClient 是一个非阻塞的、响应式的客户端,用于执行HTTP请求。它在5.0中引入,提供了 RestTemplate 的替代方案,支持同步、异步和流式场景。

WebClient 支持以下特性:

  • 非阻塞 I/O。

  • Reactive Streams 背压。

  • 以较少的硬件资源实现高并发性。

  • 函数式、fluent API,利用了Java 8 lambdas的优势。

  • 同步和异步互动。

  • 服务器的流式上传和下载。

详情见WebClient 原理及实践—官方原版

二、RestTemplate

RestTemplate 提供了一个比HTTP客户端库更高层次的API。它使得在一行中调用REST端点变得容易。它暴露了以下几组重载方法: 

Table 1. RestTemplate methods
方法组 说明

getForObject

通过 GET 检索一个表示结果。

getForEntity

通过使用GET检索一个 ResponseEntity(即 status、header 和 body)。

headForHeaders

通过使用 HEAD 检索一个资源的所有 header。

postForLocation

通过使用 POST 创建一个新的资源,并从响应中返回 Location header。

postForObject

通过使用POST创建一个新资源,并从响应中返回表示。

postForEntity

通过使用POST创建一个新资源,并从响应中返回表示。

put

通过使用PUT创建或更新一个资源。

patchForObject

通过使用 PATCH 更新一个资源,并从响应中返回表示。请注意,JDK的 HttpURLConnection 不支持 PATCH,但 Apache 的 HttpComponents 和其他的支持。

delete

通过使用 DELETE 删除指定URI上的资源。

optionsForAllow

通过使用 ALLOW 为资源检索允许的HTTP方法。

exchange

前面的方法的更通用(和更少的意见)版本,在需要时提供额外的灵活性。它接受一个 RequestEntity(包括HTTP方法、URL、header 和 body 作为输入)并返回一个 ResponseEntity

这些方法允许使用 ParameterizedTypeReference 而不是 Class 来指定一个具有泛型的响应类型。

execute

执行请求的最通用方式,通过回调接口对请求准备和响应提取进行完全控制。

1、初始化

默认构造函数使用 java.net.HttpURLConnection 来执行请求。你可以通过 ClientHttpRequestFactory 的实现切换到不同的HTTP库。有内置的对以下内容的支持:

  • Apache HttpComponents

  • Netty

  • OkHttp

例如,要切换 到Apache HttpComponents,你可以使用以下方法:

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

每个 ClientHttpRequestFactory 都公开了底层HTTP客户端库的特定配置选项—​例如,对于凭证、连接池和其他细节。

URI

许多 RestTemplate 方法接受URI模板和URI模板变量,或者作为一个 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"

你可以使用 RestTemplate 的 uriTemplateHandler 属性来定制URI的编码方式。或者,你可以准备一个 java.net.URI,并把它传入接受 URI 的 RestTemplate 方法之一。

Header

你可以使用 exchange() 方法来指定 header,如下例所示:

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

你可以通过许多返回 ResponseEntity 的 RestTemplate 方法变体获得响应头信息。

2、Body

在 HttpMessageConverter 的帮助下,传入 RestTemplate 方法和从 RestTemplate 方法返回的对象被转换为原始内容。

在POST中,一个输入对象被序列化到请求体中,如下面的例子所示:

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

你不需要明确地设置请求的 Content-Type 头。在大多数情况下,你可以根据源对象类型找到一个兼容的消息转换器(message converter),所选择的消息转换器会相应地设置 content type。如果有必要,你可以使用 exchange 方法来明确地提供 Content-Type 的请求头,而这又会影响到选择何种消息转换器。

在一个GET中,响应的 body 被反序列化为一个输出 Object,如下例所示:

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

请求的 Accept 标头不需要明确设置。在大多数情况下,可以根据预期的响应类型找到一个兼容的消息转换器,然后帮助填充 Accept 头。如果有必要,你可以使用 exchange 方法来明确提供 Accept 头。 默认情况下,RestTemplate 注册了所有内置的 消息转换器(message converter),这取决于 classpath 检查,有助于确定有哪些可选的 converter 库存在。你也可以明确地设置要使用的消息转换器。

消息转换

spring-web 模块包含 HttpMessageConverter contract,用于通过 InputStream 和 OutputStream 读写 HTTP 请求和响应的 body。HttpMessageConverter 实例在客户端(例如,在 RestTemplate 中)和服务器端(例如,在Spring MVC REST controller 中)使用。

框架中提供了主要 type(MIME)type 的具体实现,默认情况下,在客户端与 RestTemplate 注册,在服务器端与 RequestMappingHandlerAdapter 注册

HttpMessageConverter 的实现将在下面几节中描述。对于所有的转换器,都使用默认的 media type,但是你可以通过设置 supportedMediaTypes bean 属性来覆盖它。下表描述了每个实现:

Table 2. HttpMessageConverter 实现
MessageConverter 说明

StringHttpMessageConverter

一个 HttpMessageConverter 实现,可以从HTTP请求和响应中读写 String 实例。默认情况下,这个转换器支持所有的文本媒体类型(text/*),并以 text/plain 的 Content-Type 进行写入。

FormHttpMessageConverter

一个 HttpMessageConverter 实现,可以从HTTP请求和响应中读写表单数据。默认情况下,这个转换器读取和写入 application/x-www-form-urlencoded 媒体类型。表单数据从一个 MultiValueMap<String, String> 中读取并写入。该转换器还可以写入(但不读取)从 MultiValueMap<String, Object> 中读取的 multipart 数据。默认情况下,支持 multipart/form-data。从Spring Framework 5.2开始,可以支持额外的 multipart subtype 来写入表单数据。请查阅 FormHttpMessageConverter 的 javadoc 以了解更多细节。

ByteArrayHttpMessageConverter

一个 HttpMessageConverter 实现,可以从HTTP请求和响应中读写字节数。默认情况下,这个转换器支持所有的 media type(*/*),并以 application/octet-stream 为 Content-Type 进行写入。你可以通过设置 supportedMediaTypes 属性和覆盖 getContentType(byte[]) 来重写这一点。

MarshallingHttpMessageConverter

一个 HttpMessageConverter 实现,通过使用 org.springframework.oxm 包中 Spring 的 Marshaller 和 Unmarshaller 抽象,可以读写XML。这个转换器在使用前需要一个 Marshaller 和 Unmarshaller。你可以通过构造函数或Bean属性注入这些东西。默认情况下,这个转换器支持 text/xml 和 application/xml

MappingJackson2HttpMessageConverter

一个 HttpMessageConverter 实现,通过使用 Jackson 的 ObjectMapper 可以读写JSON。你可以通过使用Jackson提供的注解,根据需要定制JSON映射。当你需要进一步控制时(对于需要为特定类型提供自定义JSON serializers/deserializers 的情况),你可以通过 ObjectMapper 属性注入一个自定义 ObjectMapper。默认情况下,这个转换器支持 application/json

MappingJackson2XmlHttpMessageConverter

一个 HttpMessageConverter 的实现,可以通过使用 Jackson XML 扩展的 XmlMapper 来读写XML。你可以根据需要通过使用JAXB或Jackson提供的注解来定制XML映射。当你需要进一步控制时(对于需要为特定类型提供自定义XML serializers/deserializers 的情况),你可以通过 ObjectMapper 属性注入一个自定义 XmlMapper。默认情况下,这个转换器支持 application/xml

SourceHttpMessageConverter

一个 HttpMessageConverter 实现,可以从HTTP请求和响应中读写 javax.xml.transform.Source。只有 DOMSourceSAXSource 和 StreamSource 被支持。默认情况下,这个转换器支持 text/xml 和 application/xml

BufferedImageHttpMessageConverter

一个 HttpMessageConverter 实现,可以从HTTP请求和响应中读写 java.awt.image.BufferedImage。这个转换器读取和写入Java I/O API支持的 media type。

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

4、Multipart

为了发送 multipart 数据,你需要提供一个 MultiValueMap<String, Object>,其值可以是一个用于 part 内容的 Object,一个用于文件 part 的 Resource,或者一个用于带有 header 的 part 内容的 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));

在大多数情况下,你不需要为每个 part 指定 Content-Type。content type 是根据为序列化它而选择的 HttpMessageConverter 自动确定的,或者在 Resource 的情况下,根据文件扩展名确定。如果有必要,你可以用一个 HttpEntity wrapper 明确地提供 MediaType

一旦 MultiValueMap 准备好了,你就可以把它传递给 RestTemplate,如下所示:

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

如果 MultiValueMap 至少包含一个非 String 值,Content-Type 就被 FormHttpMessageConverter 设置为 multipart/form-data。如果 MultiValueMap 有 String 值,Content-Type 被默认为 application/x-www-form-urlencoded。如果有必要,也可以明确设置 Content-Type

三、HTTP 接口

Spring框架允许你将HTTP服务定义为一个Java接口,并为 HTTP exchange 提供注解方法。然后你可以生成一个实现该接口并执行 exchange 的代理。这有助于简化HTTP远程访问,因为远程访问通常涉及到一个 facade,该 facade 包装了使用底层HTTP客户端的细节。

声明一个带有 @HttpExchange 方法的接口:

interface RepositoryService {

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

    // more HTTP exchange methods...

}

创建一个代理,执行所声明的 HTTP exchange:

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

}

1、方法参数

注解式 HTTP exchange 方法支持灵活的方法签名,有以下方法参数:

方法参数 说明

URI

动态设置请求的URL,覆盖注解的 url 属性。

HttpMethod

动态地设置请求的HTTP方法,覆盖注解的 method 属性

@RequestHeader

添加一个请求头或多个头。参数可以是一个 Map<String, ?> 或 MultiValueMap<String, ?> 的多个头,一个 Collection<?>,或一个单独的值。对于非 String 值,支持类型转换。

@PathVariable

添加一个变量,用于在请求URL中扩展一个占位符。参数可以是一个带有多个变量的 Map<String, ?>,也可以是一个单独的值。对于非 String 值,支持类型转换。

@RequestBody

提供请求的 body,可以是要被序列化的对象,也可以是Reactive Streams Publisher,如 MonoFlux,或通过配置的 ReactiveAdapterRegistry 支持的任何其他异步类型。

@RequestParam

添加一个请求参数或多个参数。参数可以是一个 Map<String, ?> 或 MultiValueMap<String, ?> 的多个参数,一个 Collection<?> ,或一个单独的值。对于非 String 值,支持类型转换。

当 "content-type" 被设置为 "application/x-www-form-urlencoded" 时,请求参数被编码在请求体中。否则,它们被添加为URL查询参数。

@RequestPart

添加一个 request part,它可以是一个 String(表单字段)、Resource(文件 part)、对象(要编码的实体,如JSON)、HttpEntity(part 内容和 header)、Spring Part 或上述任何一个的 Reactive Streams Publisher

@CookieValue

添加一个或多个cookie。参数可以是一个 Map<String, ?> 或 MultiValueMap<String, ?> 的多个cookie,一个 Collection<?>,或一个单独的值。对于非 String 值,支持类型转换。

2、返回值

注解式 HTTP exchange 方法支持以下返回值:

方法返回值 说明

voidMono<Void>

执行给定的请求,并释放响应内容,如果有的话。

HttpHeadersMono<HttpHeaders>

执行给定的请求,释放响应内容(如果有),并返回响应头信息。

<T>Mono<T>

执行给定的请求并将响应内容解码为声明的返回类型。

<T>Flux<T>

执行给定的请求,并将响应内容解码为声明的元素类型的流。

ResponseEntity<Void>Mono<ResponseEntity<Void>>

执行给定的请求,并释放响应内容(如果有的话),并返回一个带有状态和头信息的 ResponseEntity

ResponseEntity<T>Mono<ResponseEntity<T>>

执行给定的请求,将响应内容解码为声明的返回类型,并返回一个带有状态、头信息和解码后的 body 的 ResponseEntity

Mono<ResponseEntity<Flux<T>>

执行给定的请求,将响应内容解码为声明的元素类型的流,并返回一个带有状态、头信息和解码后的响应体流的 ResponseEntity

3、异常处理

默认情况下,WebClient 会对 4xx 和 5xx HTTP状态代码引发 WebClientResponseException。要定制这一点,你可以注册一个响应状态 handler,适用于通过客户端执行的所有响应:

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

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

关于更多的细节和选项,例如抑制错误状态代码,请参见 WebClient.Builder 中 defaultStatusHandler 的 Javadoc。

大家好,我是Doker品牌的Sinbad,欢迎点赞和评论,您的鼓励是我们持续更新的动力!欢迎加微信进入技术群聊!文章来源地址https://www.toymoban.com/news/detail-728874.html

到了这里,关于Spring 教程—REST 客户端详解(WebClient 、RestTemplate、HTTP 接口)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Spring Cloud(Finchley版本)系列教程(二) 客户端负载均衡Ribbon

    Spring Cloud(Finchley版本)系列教程(二) 客户端负载均衡Ribbon

    Spring Cloud(Finchley版本)系列教程(二) 客户端负载均衡Ribbon 目前主流的负载均衡方案有两种,一种是集中式均衡负载,在消费者与服务提供者之间使用独立的代理方式进行负载,比如F5、Nginx等。另一种则是客户端自己做负载均衡,根据自己的请求做负载,Ribbon就属于客户端自己

    2024年02月09日
    浏览(30)
  • Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

    Spring MVC学习随笔-控制器(Controller)开发详解:接受客户端(Client)请求参数

    学习视频:孙哥说SpringMVC:结合Thymeleaf,重塑你的MVC世界!|前所未有的Web开发探索之旅 💡 1. 接受客户端(client)请求参数[讲解]2. 调用业务对象3. 页面跳转 所谓简单变量:指的就是8种基本类型+String这些类型的变量。把这些类型的变量,作为控制器方法的形参,用于接受

    2024年02月05日
    浏览(23)
  • es相关的官方客户端与spring客户端对比与介绍

    es相关的官方客户端与spring客户端对比与介绍

    es提供的 TransportClient 传统的客户端,基于TCP传输协议与Elasticsearch通信。 已经被弃用,不推荐使用。 适用于Elasticsearch 5.x及以前的版本 因为Elasticsearch 6.x及以上版本已不再支持TCP Transport协议,TransportClient无法连接Elasticsearch集群。 RestHighLevelClient 是一个高级的REST客户端,主要用于与

    2024年02月02日
    浏览(14)
  • Spring Cloud【Config客户端配置与测试、Config客户端之动态刷新 、什么是Spring Cloud Bus、Docker安装RabbitMQ】(十)

    Spring Cloud【Config客户端配置与测试、Config客户端之动态刷新 、什么是Spring Cloud Bus、Docker安装RabbitMQ】(十)

      目录 分布式配置中心_Config客户端配置与测试 为什么要引入bootstrap 

    2024年02月15日
    浏览(12)
  • Msquic客户端详解

    Msquic客户端详解

    Msquic用起来还是很方便很直观的 因为微软喜欢玩句柄 所以很多对象都由如下形式提供 Tips:关于微软为啥喜欢句柄请自行百度  我们来看看github官网 微软给出的对象有哪些 下图来自Msquic github  下面这段解释来自微软github msquic/API.md at main · microsoft/msquic · GitHub 这里一起贴出

    2024年02月06日
    浏览(6)
  • Trojan客户端使用教程

    此教程使用的是 Centos7 x86_64系统 使用此命令下载Trojan客户端 官方版本(GitHub): cd /usr/src wget https://github.com/trojan-gfw/trojan/releases/download/v1.15.1/trojan-1.15.1-linux-amd64.tar.xz 解压Trojan文件 tar xvf trojan-1.15.1-linux-amd64.tar.xz 打开配置文件 cd /usr/src/trojan vi config.json 按i进入编辑模式 run_typ

    2024年02月02日
    浏览(16)
  • 客户端Git安装教程

    客户端Git安装教程

    首先打开Git官网https://git-scm.com/ 然后选择合适的版本去下载,我的电脑是64位的,查看自己电脑是什么操作系统,右击【我的电脑】—属性  就看到了 接下来就是双击下载好的安装包,同意条款,选择安装路径 然后就是选择选项配置,按照默认的来就行,不用修改 第三个界

    2024年02月08日
    浏览(12)
  • SVN客户端使用教程

    SVN客户端使用教程

    正式进入公司项目后,我们需要和同事进行协同开发,此时代码管理工具是必不可少的,目前常用的两款工具是:SVN 和 Git。本人因为要搭建一个自动化测试的框架,对SVN和Git都不熟悉,在调研后选择了操作更为简单的代码管理工具:SVN。 SVN是什么? 全称Subversion,属于集中

    2024年02月08日
    浏览(12)
  • Spring Boot 整合 Redis,使用 RedisTemplate 客户端

    Spring Boot 整合 Redis,使用 RedisTemplate 客户端

    1.1.1 添加依赖 redis 的依赖: 1.1.2 yml 配置文件 1.1.3 Config 配置文件 1.1.4 使用示例 注入 RedisTemplate,即可操作 Redis,简单示例如下: 1.2.1 RedisTemplate 简介 RedisTemplate 是 Spring Data Redis 项目的一部分,旨在简化在Java应用程序中使用 Redis 的过程。它提供了一组简单的方法,可以在

    2024年02月09日
    浏览(17)
  • kafka客户端应用参数详解

    kafka客户端应用参数详解

    Kafka提供了非常简单的客户端API。只需要引入一个Maven依赖即可: 1、消息发送者主流程  然后可以使用Kafka提供的Producer类,快速发送消息。 ​ 整体来说,构建Producer分为三个步骤: 设置Producer核心属性  :Producer可选的属性都可以由ProducerConfig类管理。比如ProducerConfig.BOOTST

    2024年02月07日
    浏览(15)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包