环境:SpringBoot3.2.1
1. 简介
客户端执行HTTP请求,在底层的HTTP客户端库(如JDK HttpClient、ApacheHttpComponents等)上公开流畅、同步的API。
RestClient是一个同步HTTP客户端,它提供了一个现代、流畅的API。它提供了对HTTP库的抽象,允许从Java对象到HTTP请求的方便转换,以及从HTTP响应创建对象。
2. 创建RestClient实例
RestClient是使用一个静态create方法创建的。还可以通过builder来获得带有进一步选项的builder,例如指定使用哪个HTTP库和使用哪个消息转换器,设置默认URI、默认路径变量、默认请求头或uriBuilderFactory,或注册拦截器和初始化器。
一旦创建(或构建),RestClient就可以被多个线程安全地使用。
示例:
// 简单create方式
RestClient defaultClient = RestClient.create() ;
// 通过builder构建
RestClient customClient = RestClient.builder()
.requestFactory(new HttpComponentsClientHttpRequestFactory())
.messageConverters(converters -> converters.add(new PackCustomMessageConverter()))
.baseUrl("http://api.pack.com")
.defaultUriVariables(Map.of("name", "zs"))
.defaultHeader("My-Header", "Foo")
.requestInterceptor(...)
.requestInitializer(...)
.build() ;
3. 使用RestClient
当使用RestClient发出HTTP请求时,首先要指定使用哪个HTTP方法。这可以使用method(HttpMethod),或者使用便利方法get()、head()、post()等来完成。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient.get() ;
restClient.post() ;
// 或
restClient.method(HttpMethod.GET) ;
3.1 Request URI
接下来,可以用URI方法指定请求URI。此步骤是可选的,如果RestClient配置了默认URI,则可以跳过此步骤。URL通常指定为字符串,带有可选的URI模板变量。默认情况下,字符串url是编码的,但是可以通过使用自定义uriBuilderFactory构建客户端来更改。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient.method(HttpMethod.GET).uri("/users") ;
3.2 Request Headers And Body
如果有必要,可以通过添加请求头header(String, String)、header(Consumer),或者使用便利方法accept(MediaType…)、acceptCharset(Charset…)等来操作HTTP请求。对于可以包含正文(POST、PUT和PATCH)的HTTP请求,还有其他方法:contentType(MediaType)和contentLength(long)。
请求体本身可以通过body(Object)设置,它在内部使用HTTP消息转换。或者,可以使用ParameterizedTypeReference设置请求体,这样就可以使用泛型。最后,函数体可以设置为一个回调函数,用于写入OutputStream。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient
.post()
.uri("/users")
.body(new User(666L, "张三", 23))
.header("X-API-VERSION", "1.0")
3.3 获取响应结果
设置好请求后,调用retrieve()方法访问HTTP响应。可以使用body(Class)或body(ParameterizedTypeReference)来访问响应主体,参数化类型如列表。body方法将响应内容转换为各种类型,例如bytes可以转换为字符串,JSON可以使用Jackson转换为对象等。
响应也可以被转换为ResponseEntity,以便访问响应头和响应体。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient
.get()
.uri("/users/666")
.retrieve()
.body(User.class) ;
通过ResponseEntity可以访问响应的状态码和响应头:
RestClient restClient = RestClient.create("http://api.pack.com") ;
ResponseEntity result = restClient.get()
.uri("/users/666")
.accept(APPLICATION_JSON)
.retrieve()
.toEntity(User.class) ;
System.out.println("Response status: " + result.getStatusCode());
System.out.println("Response headers: " + result.getHeaders());
System.out.println("Contents: " + result.getBody());
3.4 错误处理
默认情况下,当返回的状态码为4xx或5xx的响应时,RestClient会抛出RestClientException的子类。这种行为可以用onStatus来覆盖。
String result = restClient.get()
.uri("/users/{id}", id)
.retrieve()
// 自定义4xx错误
.onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders())
})
.body(String.class) ;
onStatus方法
图片
3.5 Exchange
对于更高级的场景,RestClient通过exchange方法提供对底层HTTP请求和响应的访问,可以使用该方法代替retrieve()。使用exchange时不会应用状态处理程序,因为exchange方法已经提供了对完整响应的访问,允许执行任何必要的错误处理。
RestClient restClient = RestClient.create("http://api.pack.com") ;
restClient
.post()
.uri("/users/666")
.body(new User())
.header("X-API-VERSION", "1.0")
.exchange((request, response) -> {
if (response.getStatusCode().is4xxClientError()) {
throw new RuntimeException(String.format("status: %d, headers: %s", response.getStatusCode(), response.getHeaders())) ;
} else {
return response.getBody() ;
}
}) ;
3.6 客户端请求工厂
RestClient使用客户端HTTP库来执行HTTP请求。这些库通过ClientRequestFactory接口进行调整。有各种可用的实现:
- JdkClientHttpRequestFactory for Java’s HttpClient,
- HttpComponentsClientHttpRequestFactory for use with Apache HTTP Components HttpClient,
- JettyClientHttpRequestFactory for Jetty’s HttpClient,
- ReactorNettyClientRequestFactory for Reactor Netty’s HttpClient,
- SimpleClientHttpRequestFactory as a simple default.
如果在构建RestClient时没有指定请求工厂,它将使用classpath中提供的Apache或Jetty HttpClient。否则,如果加载了java.net.http模块,它将使用Java的HttpClient。
以上是本篇文章的全部内容,希望对你有帮助。