restCilent官方文档(已翻译)及简单使用

rest请求选择

  • RestClient- 具有流畅 API 的同步客户端。
  • WebClient- 具有流畅 API 的非阻塞、反应式客户端。
  • RestTemplate- 具有模板方法 API 的同步客户端。
  • HTTP 接口- 带有生成的动态代理实现的注释接口。

RestCilent

  • 提供丰富的Http库,在java对象在Http请求之间灵活的转化

创建一个RestCilent

RestClient使用静态方法之一创建。create您还可以使用builder()获取具有更多选项的构建器,例如指定要使用的 HTTP 库(请参阅客户端请求工厂)和要使用的消息转换器(请参阅HTTP 消息转换)、设置默认 URI、默认路径变量、默认请求标头或uriBuilderFactory,或者注册拦截器和初始化程序。

//简单的创建
RestClient defaultClient = RestClient.create();
//以配置的方式进行创建
RestClient customClient = RestClient.builder()
  .requestFactory(new HttpComponentsClientHttpRequestFactory())
  .messageConverters(converters -> converters.add(new MyCustomMessageConverter()))
  .baseUrl("https://example.com")
  .defaultUriVariables(Map.of("variable", "foo"))
  .defaultHeader("My-Header", "Foo")
  .requestInterceptor(myCustomInterceptor)
  .requestInitializer(myCustomInitializer)
  .build();

使用RestCilent

使用 发出 HTTP 请求时RestClient,首先要指定要使用的 HTTP 方法。可以使用method(HttpMethod)或便捷方法get()head()post()等来完成此操作。

请求url

此步骤是可选的,如果配置了默认 URI,则可以跳过RestClient此步骤。URL 通常指定为String,带有可选的 URI 模板变量。以下示例将 GET 请求配置为example.com/orders/42

int id = 42;
restClient.get()
  .uri("https://example.com/orders/{id}", id)
  ....
请求标头和正文

如果必要,HTTP 請求可以通過添加標頭 header(String, String)、headers(Consumer 或使用便捷方法 accept(MediaType…)、acceptCharset(Charset…) 等進行操作。對於可以包含主體的 HTTP 請求(POST、PUT 和 PATCH),還有額外的方法可用:contentType(MediaType) 和 contentLength(long)。

請求主體本身可以使用 body(Object) 設置,該方法內部使用 HTTP 訊息轉換。或者,請求主體可以使用 ParameterizedTypeReference 設置,允許您使用泛型。最後,主體可以設置為回调函數,該函數寫入 OutputStream。

检索响应

一旦请求被设置好,HTTP 响应可以通过调用 retrieve() 访问。响应体可以通过使用 body(Class) 或 body(ParameterizedTypeReference) 访问,用于参数化类型,如列表。body 方法将响应内容转换为各种类型 - 例如,字节可以转换为字符串,JSON 可以使用 Jackson 转换为对象,等等(见 HTTP 消息转换)。

响应也可以转换为 ResponseEntity,提供对响应头和响应体的访问。

String result = restClient.get()
  .uri("https://example.com")
  .retrieve()
  .body(String.class);

System.out.println(result);
  • 发起请求
  • 定制url连接
  • 检索响应
  • 将响应转化成字符串
  • 打印
ResponseEntity<String> result = restClient.get()
  .uri("https://example.com")
  .retrieve()
  .toEntity(String.class);

System.out.println("Response status: " + result.getStatusCode());
System.out.println("Response headers: " + result.getHeaders());
System.out.println("Contents: " + result.getBody());
  • 设置指定 URL 的 GET 请求 将响应转换为 ResponseEntity 打印结果

  • RestClient 可以使用 Jackson 库将 JSON 转换为对象。请注意此示例中的 URI 变量使用和 Accept 头设置为 JSON。

int id = ...;
Pet pet = restClient.get()
  .uri("https://petclinic.example.com/pets/{id}", id)
  .accept(APPLICATION_JSON)
  .retrieve()
  .body(Pet.class);

在下一个示例中,RestClient 用于执行包含 JSON 的 POST 请求,该 JSON 又是使用 Jackson 转换的。

Pet pet = ...
ResponseEntity<Void> response = restClient.post()
  .uri("https://petclinic.example.com/pets/new")
  .contentType(APPLICATION_JSON)
  .body(pet)
  .retrieve()
  .toBodilessEntity();
  • 创建一个宠物域对象,设置一个 POST 请求,并连接到 URL
  • 将 Content-Type 头信息设置为 application/json,将宠物作为请求体
  • 将响应转换为一个无体响应实体。
错误处理

默认情况下,RestClient 在检索 4xx 或 5xx 状态码响应时抛出 RestClientException 的子类。可以使用 onStatus 覆盖此行为。

String result = restClient.get()
  .uri("https://example.com/this-url-does-not-exist")
  .retrieve()
  .onStatus(HttpStatusCode::is4xxClientError, (request, response) -> {
      throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders());
  })
  .body(String.class);

创建一个 GET 请求

用于 URL 返回 404 状态码

为所有 4xx 状态码设置状态处理程序 抛出自定义异常

Exchage

对于更高级的场景,RestClient 通过 exchange() 方法提供了对底层 HTTP 请求和响应的访问,这可以代替 retrieve()。当使用 exchange() 时,不会应用状态处理程序,因为 exchange 函数已经提供了对完整响应的访问,允许您执行任何必要的错误处理。

Pet result = restClient.get()
  .uri("https://petclinic.example.com/pets/{id}", id)
  .accept(APPLICATION_JSON)
  .exchange((request, response) -> {
    if (response.getStatusCode().is4xxClientError()) {
      throw new MyCustomRuntimeException(response.getStatusCode(), response.getHeaders());
    }
    else {
      Pet pet = convertResponse(response);
      return pet;
    }
  });
HTTP 消息转换

在响应式栈中的等效实现

spring-web 模块包含 HttpMessageConverter 接口,用于通过 InputStream 和 OutputStream 读取和写入 HTTP 请求和响应的主体。HttpMessageConverter 实例在客户端(例如,在 RestClient 中)和服务器端(例如,在 Spring MVC REST 控制器中)使用。

框架中提供了主要媒体(MIME)类型的具体实现,并默认在客户端的 RestClient 和 RestTemplate 以及服务器端的 RequestMappingHandlerAdapter 中注册(参见配置消息转换器)。

下表描述了几个 HttpMessageConverter 实现。有关所有转换器的完整列表,请参阅 HttpMessageConverter Javadoc。对于所有转换器,使用了默认的媒体类型,但您可以通过设置 supportedMediaTypes 属性来覆盖它。

消息转换器描述
StringHttpMessageConverter一个 HttpMessageConverter 实现,可以从 HTTP 请求和响应中读取和写入 String 实例。默认情况下,该转换器支持所有文本媒体类型(text/*)并以 text/plain 的 Content-Type 进行写入。
FormHttpMessageConverter一个 HttpMessageConverter 实现,可以从 HTTP 请求和响应中读取和写入表单数据。默认情况下,该转换器读取和写入 application/x-www-form-urlencoded 媒体类型。表单数据从 MultiValueMap<String, String> 中读取并写入。该转换器还可以写入(但不能读取)从 MultiValueMap<String, Object> 读取的多部分数据。默认情况下,支持 multipart/form-data。可以支持其他多部分子类型以便写入表单数据。有关详细信息,请参见 FormHttpMessageConverter 的 javadoc。
ByteArrayHttpMessageConverter一个 HttpMessageConverter 实现,可以从 HTTP 请求和响应中读取和写入字节数组。默认情况下,该转换器支持所有媒体类型(/)并以 application/octet-stream 的 Content-Type 进行写入。可以通过设置 supportedMediaTypes 属性和重写 getContentType(byte[]) 来覆盖此行为。
MarshallingHttpMessageConverter一个 HttpMessageConverter 实现,可以通过使用 Spring 的 Marshaller 和 Unmarshaller 抽象从 org.springframework.oxm 包中读取和写入 XML。在使用之前需要一个 Marshaller 和 Unmarshaller。可以通过构造函数或 bean 属性注入这些。默认情况下,该转换器支持 text/xml 和 application/xml。
MappingJackson2HttpMessageConverter一个 HttpMessageConverter 实现,可以通过使用 Jackson 的 ObjectMapper 读取和写入 JSON。可以通过 Jackson 提供的注解根据需要自定义 JSON 映射。当需要进一步控制(例如,为特定类型提供自定义 JSON 序列化/反序列化器)时,可以通过 ObjectMapper 属性注入自定义 ObjectMapper。默认情况下,该转换器支持 application/json。
MappingJackson2XmlHttpMessageConverter一个 HttpMessageConverter 实现,可以通过使用 Jackson XML 扩展的 XmlMapper 读取和写入 XML。可以通过 JAXB 或 Jackson 提供的注解根据需要自定义 XML 映射。当需要进一步控制(例如,为特定类型提供自定义 XML 序列化/反序列化器)时,可以通过 ObjectMapper 属性注入自定义 XmlMapper。默认情况下,该转换器支持 application/xml。
SourceHttpMessageConverter一个 HttpMessageConverter 实现,可以从 HTTP 请求和响应中读取和写入 javax.xml.transform.Source。仅支持 DOMSource、SAXSource 和 StreamSource。默认情况下,该转换器支持 text/xml 和 application/xml。

默认情况下,RestClient 和 RestTemplate 会注册所有内置消息转换器,这取决于类路径上底层库的可用性。您还可以通过在 RestClient 构建器上使用 messageConverters() 方法或通过 RestTemplate 的 messageConverters 属性显式设置要使用的消息转换器。

Jackson JSON视图

在Java中,为了只序列化对象属性的子集,可以使用Jackson JSON视图(View),如下面的例子所示。

MappingJacksonValue value = new MappingJacksonValue(new User("eric", "7!jd#h23"));
value.setSerializationView(User.WithoutPasswordView.class);

ResponseEntity<Void> response = restClient.post() // or RestTemplate.postForEntity
  .contentType(APPLICATION_JSON)
  .body(value)
  .retrieve()
  .toBodilessEntity();
Multipart

要发送多部分数据,您需要提供一个MultiValueMap,其值可以是部分内容的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));

// send using RestClient.post or RestTemplate.postForEntity

在大多数情况下,您不必为每个部分指定Content-Type。内容类型是根据选择序列化它的HttpMessageConverter自动确定的,或者在资源的情况下,根据文件扩展名自动确定的。如果有必要,您可以显式地为MediaType提供HttpEntity包装器。一旦MultiValueMap准备好了,您就可以使用RestClient.post().body(parts)(或RestTemplate.postForObject)将其用作POST请求的主体。如果MultiValueMap包含至少一个非string值,则Content-Type被FormHttpMessageConverter设置为multipart/form-data。如果MultiValueMap有String值,则Content-Type默认为application/x-www-form-urlencoded。如果有必要,Content-Type也可以显式设置。

Client Request Factories

为了执行HTTP请求,RestClient使用客户端HTTP库。这些库通过ClientRequestFactory接口进行调整。各种实现是可用的

  • JdkClientHttpRequestFactory用于Java的
  • HttpClient•HttpComponentsClientHttpRequestFactory用于Apache HTTP组件HttpClient•JettyClientHttpRequestFactory用于Jetty的HttpClient•reactornetttclientrequestfactory用于反应器Netty的HttpClient•SimpleClientHttpRequestFactory作为一个简单的默认值

如果在构建RestClient时没有指定请求工厂,它将使用Apache或Jetty HttpClient(如果它们在类路径上可用)。否则,如果加载了java.net.http模块,它将使用Java的HttpClient。最后,它将采用简单的默认值。

WebClient

WebClient是一个非阻塞的响应式客户端,用于执行HTTP请求。它是在5.0中引入的,提供了RestTemplate的替代方案,支持同步、异步和流场景。WebClient支持以下内容:•非阻塞I/O•响应式流反压•用更少的硬件资源实现高并发性•函数式、流畅的API(利用Java 8 lambda)•同步和异步交互•从服务器流上或流下参见WebClient。

RestTemplate 方法

以下是 RestTemplate 提供的方法:

getForObject

通过 GET 获取表示。

getForEntity

通过 GET 获取 ResponseEntity(包括状态、头和体)。

headForHeaders

通过 HEAD 获取资源的所有头。

postForLocation

通过 POST 创建新资源并返回响应中的 Location 头。

postForObject

通过 POST 创建新资源并返回响应中的表示。

postForEntity

通过 POST 创建新资源并返回响应中的 ResponseEntity。

put

通过 PUT 创建或更新资源。

patchForObject

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

delete

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

optionsForAllow

通过 ALLOW 获取资源的允许 HTTP 方法。

exchange

一个更通用的(且不那么 opinionated 的)方法,提供了在需要时额外的灵活性。它接受一个 RequestEntity(包括 HTTP 方法、URL、头和体作为输入)并返回一个 ResponseEntity。

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

execute

执行请求的最通用方式,提供了对请求的完全控制。

RestTemplate 方法

以下是 RestTemplate 提供的方法:

getForObject

通过 GET 获取表示。

getForEntity

通过 GET 获取 ResponseEntity(包括状态、头和体)。

headForHeaders

通过 HEAD 获取资源的所有头。

postForLocation

通过 POST 创建新资源并返回响应中的 Location 头。

postForObject

通过 POST 创建新资源并返回响应中的表示。

postForEntity

通过 POST 创建新资源并返回响应中的 ResponseEntity。

put

通过 PUT 创建或更新资源。

patchForObject

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

delete

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

optionsForAllow

通过 ALLOW 获取资源的允许 HTTP 方法。

exchange

一个更通用的(且不那么 opinionated 的)方法,提供了在需要时额外的灵活性。它接受一个 RequestEntity(包括 HTTP 方法、URL、头和体作为输入)并返回一个 ResponseEntity。

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

execute

执行请求的最通用方式,提供了对请求的完全控制。

Initialization

RestTemplate使用与RestClient相同的HTTP库抽象。默认情况下,它使用SimpleClientHttpRequestFactory,但这可以通过构造函数进行更改。参见客户端请求工厂。

Body

传入RestTemplate方法和从RestTemplate方法返回的对象在HttpMessageConverter的帮助下转换为HTTP消息,参见HTTP消息转换。

HTTP Interface

Spring框架允许您使用**@HttpExchange**方法将HTTP服务定义为Java接口。你可以将这样的接口传递给HttpServiceProxyFactory来创建一个代理,该代理通过HTTP客户端(如RestClient或WebClient)执行请求。您还可以从@Controller实现用于服务器请求处理的接口。

首先使用@HttpExchange方法创建接口:

interface RepositoryService {

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

	// more HTTP exchange methods...

}

现在,您可以创建一个代理,在调用方法时执行请求。

For RestClient:

RestClient restClient = RestClient.builder().baseUrl("https://api.github.com/").build();
RestClientAdapter adapter = RestClientAdapter.create(restClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();

RepositoryService service = factory.createClient(RepositoryService.class);

For WebClient:

WebClient webClient = WebClient.builder().baseUrl("https://api.github.com/").build();
WebClientAdapter adapter = WebClientAdapter.create(webClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();

RepositoryService service = factory.createClient(RepositoryService.class);

在类型级别支持@HttpExchange,它适用于所有方法:J

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

}
Method parameter

注释后,HTTP交换方法支持灵活的方法签名,方法参数如下:

Here is the translation of the text about method arguments:

方法参数

以下是方法参数的描述:

URI

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

UriBuilderFactory

提供一个 UriBuilderFactory 来扩展 URI 模板和 URI 变量。实际上,替换了底层客户端的 UriBuilderFactory(及其基础 URL)。

HttpMethod

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

@RequestHeader

添加一个或多个请求头。参数可以是一个 Map<String, ?> 或 MultiValueMap<String, ?>,包含多个头,一个 Collection<?> 的值,或者一个单个值。支持非字符串值的类型转换。

@PathVariable

添加一个变量来扩展请求 URL 中的占位符。参数可以是一个 Map<String, ?>,包含多个变量,或者一个单个值。支持非字符串值的类型转换。

@RequestAttribute

提供一个对象作为请求属性。仅支持 WebClient。

@RequestBody

提供请求体,either as an Object to be serialized, or a Reactive Streams Publisher such as Mono, Flux, or any other async type supported through the configured ReactiveAdapterRegistry。

@RequestParam

添加一个或多个请求参数。参数可以是一个 Map<String, ?> 或 MultiValueMap<String, ?>,包含多个参数,一个 Collection<?> 的值,或者一个单个值。支持非字符串值的类型转换。

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

@RequestPart

添加一个请求部分,可能是一个 String(表单字段),Resource(文件部分),Object(要编码的实体,例如 JSON),HttpEntity(部分内容和头),Spring Part,或者 Reactive Streams Publisher 的任何上述类型。

MultipartFile

从 MultipartFile 添加一个请求部分,通常在 Spring MVC 控制器中使用,表示上传的文件。

@CookieValue

添加一个或多个 cookie。参数可以是一个 Map<String, ?> 或 MultiValueMap<String, ?>,包含多个 cook适应了ReactorHttpExchangeAdapter的客户端,比如WebClient,支持上述所有功能以及响应式变体。下表显示了反应器类型,但你也可以使用ReactiveAdapterRegistry支持的其他响应类型:ie,一个 Collection<?> 的值,或者一个单个值。支持非字符串值的类型转换。

适应了ReactorHttpExchangeAdapter的客户端,比如WebClient,支持上述所有功能以及响应式变体。下表显示了反应器类型,但你也可以使用ReactiveAdapterRegistry支持的其他响应类型:

默认情况下,WebClient会对4xx和5xx HTTP状态码引发WebClientResponseException异常。要定制这一点,请注册一个响应状态处理程序,该处理程序应用于通过客户机执行的所有响应:

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

WebClientAdapter adapter = WebClientAdapter.create(webClient);
HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(adapter).build();

在项目中使用

接口

@HttpExchange(accept = MediaType.APPLICATION_JSON_VALUE)
public interface StudentProxy {
//    @HttpExchange方法将HTTP服务定义为Java接口
    @GetExchange("/hello/student")
    public String hello(@RequestParam String name);
    @PostExchange("get/student")
    public Student getStudent(@RequestParam String name);
}

使用工厂模式创建 StudentProxy

@Configuration
public class RestClientProxyConfig {
    @Autowired
    StudentProperty studentProperty;
    @Bean
    public StudentProxy studentProxy() {
        RestClient restClient = RestClient.builder().baseUrl(studentProperty.getUrl()).build();
        RestClientAdapter adapter = RestClientAdapter.create(restClient);
        HttpServiceProxyFactory factory = HttpServiceProxyFactory.builderFor(adapter).build();
        return factory.createClient(StudentProxy.class);
    }

}

在注入完成使用

@SpringBootTest
public class testRest {
    @Autowired
   private StudentProxy studentProxy;
    @Test
    public void test() {
        String hello = studentProxy.hello("小米");
        System.out.println(hello);
    }
    @Test
    public void test2() {
        Student xiaomi = studentProxy.getStudent("小米");
        System.out.println(xiaomi);
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值