SpringBoot是一个基于Spring的快速开发框架,它可以帮助我们快速构建、部署和运行Java应用程序。HTTP接口是Web应用程序与外部系统进行通信的一种方式,通过HTTP协议,我们可以实现客户端与服务器之间的数据交互。
SpringBoot 整合提供了很多方式进行远程调用
- 轻量级客户端方式
RestTemplate
: 普通开发WebClient
: 响应式编程开发Http Interface
: 声明式编程
在 Spring WebFlux 中,Mono 和 Flux 都是响应式编程的工具,用于处理异步数据流。
Mono
: 是一个单例的、不可变的、最终的、完成的、包含单个元素的数据流,它只能发出一个元素。
Flux
: 是一个可变的、无限的、最终的、未完成的数据流,它可以发出任意数量的元素。
声明式客户端
声明式 http 客户端主旨是使得编写 java http 客户端更容易。为了贯彻这个理念,采用了通过处理注解来自动生成请求的方式(官方称呼为声明式、模板化)。通过声明式 http 客户端实现我们就可以在 java 中像调用一个本地方法一样完成一次 http 请求,大大减少了编码成本,同时提高了代码可读性。
测试环境
SpringBoot3.0.6,JDK17
1. WebClient
WebClient 是Spring WebFlux 模块提供的一个非阻塞的基于响应式编程的进行 Http 请求的客户端工具。完全非阻塞,支持流式处理。
1.1 创建与配置
发请求:
- 请求方式: GETPOSTDELETE...
- 请求路径: /...
- 请求参数:aa=bb&cc=dd&xxx
- 请求头: aa=bb,cc=ddd
- 请求体:
创建
WebClient
: WebClient.create()
WebClient.create(String baseUrl)
使用WebClient.builder()
配置更多参数:uriBuilderFactory
: 自定义UriBuilderFactory
,定义 baseurl.defaultUriVariables
: 默认 uri 变量.defaultHeader
: 每个请求默认头.defaultCookie
: 每个请求默认 cookie.defaultRequest
: Consumer 自定义每个请求.filter
: 过滤 client 发送的每个请求exchangeStrategies
: HTTP 消息 reader/writer 自定义.clientConnector
: HTTP client 库设置.
pom依赖:
代码语言:html复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
代码语言:java复制WebClient webClient = WebClient.create("https://api.qqsuu.cn");
1.2 获取响应
代码语言:java复制
retrieve()
方法用来声明如何提取响应数据。比如
//获取响应完整信息
WebClient client = WebClient.create("https://example.org");
Mono<ResponseEntity<Person>> result = client.get()
.uri("/persons/{id}", id).accept(MediaType.APPLICATION_JSON)
.retrieve()
.toEntity(Person.class);
//只获取body
WebClient client = WebClient.create("https://example.org");
Mono<Person> result = client.get()
.uri("/persons/{id}", id).accept(MediaType.APPLICATION_JSON)
.retrieve()
.bodyToMono(Person.class);
//stream数据
Flux<Quote> result = client.get()
.uri("/quotes").accept(MediaType.TEXT_EVENT_STREAM)
.retrieve()
.bodyToFlux(Quote.class);
//定义错误处理
Mono<Person> result = client.get()
.uri("/persons/{id}", id).accept(MediaType.APPLICATION_JSON)
.retrieve()
.onStatus(HttpStatus::is4xxClientError, response -> ...)
.onStatus(HttpStatus::is5xxServerError, response -> ...)
.bodyToMono(Person.class);
1.3 定义请求体
代码语言:java复制//1、响应式-单个数据
Mono<Person> personMono = ... ;
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.body(personMono, Person.class)
.retrieve()
.bodyToMono(Void.class);
//2、响应式-多个数据
Flux<Person> personFlux = ... ;
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_STREAM_JSON)
.body(personFlux, Person.class)
.retrieve()
.bodyToMono(Void.class);
//3、普通对象
Person person = ... ;
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(person)
.retrieve()
.bodyToMono(Void.class);
2. HTTP Interface
从 Spring 6 和 Spring Boot 3 开始,Spring 框架支持将远程 HTTP 服务代理成带有特定注解的 Java http interface。类似的库,如 OpenFeign 和 Retrofit 仍然可以使用,但 http interface 为 Spring 框架添加内置支持。
HTTP Interface可以将 HTTP 服务定义成一个包含特定注解标记的方法的 Java 接口,然后通过对接口方法的调用,完成 HTTP 请求。
2.1 定义接口
代码语言:java复制public interface BingService {
@GetExchange(url = "/search")
String search(@RequestParam("keyword") String keyword);
}
2.2 创建代理&测试
代码语言:java复制@SpringBootTest
class Boot05TaskApplicationTests {
@Test
void contextLoads() throws InterruptedException {
//1、创建客户端
WebClient client = WebClient.builder()
.baseUrl("https://cn.bing.com")
.codecs(clientCodecConfigurer -> {
clientCodecConfigurer
.defaultCodecs()
.maxInMemorySize(256*1024*1024);
//响应数据量太大有可能会超出BufferSize,所以这里设置的大一点
})
.build();
//2、创建工厂
HttpServiceProxyFactory factory = HttpServiceProxyFactory
.builder(WebClientAdapter.forClient(client)).build();
//3、获取代理对象
BingService bingService = factory.createClient(BingService.class);
//4、测试调用
Mono<String> search = bingService.search("chatgpt是什么");
System.out.println("==========");
//return search;
search.subscribe(str -> System.out.println(str));
Thread.sleep(100000);
}
}