美文网首页
Spring5之WebClient简单使用

Spring5之WebClient简单使用

作者: 因你而在_caiyq | 来源:发表于2020-11-02 22:01 被阅读0次

    原创文章,转载请注明原文章地址,谢谢!

    Spring3.0引入了RestTemplate,但是在后来的官方源码中介绍,RestTemplate有可能在未来的版本中被弃用,所谓替代RestTemplate,在Spring5中引入了WebClient作为非阻塞式Reactive Http客户端。

    传统阻塞IO模型

    采用阻塞IO模式获取输入数据。每个连接都需要独立的线程,完成数据输入、业务处理、返回。传统阻塞IO模型的问题是,当并发数很大时,就要创建大量线程,占用很大的系统资源。连接创建后,如果当前线程暂时没有数据可读,该线程会阻塞在read操作,造成线程资源浪费。

    阻塞IO模型图

    响应式IO模型

    SpringMVC或Struct等框架都是基于Servlet的,其底层IO模型是阻塞IO模型。Spring社区为了解决SpringMVC的阻塞模型在高并发场景下的性能瓶颈,推出了Spring WebFlux,WebFlux底层实现是久经考验的Netty非阻塞IO通信框架。其实WebClient处理单个HTTP请求的响应时长并不比RestTemplate更快,但是它处理并发的能力更强。 所以响应式非阻塞IO模型的核心意义在于,提高了单位时间内有限资源下的服务请求的并发处理能力,而不是缩短了单个服务请求的响应时长。

    Netty的请求处理与线程交互的关系图
    与RestTemplate相比,WebClient的优势
    • 非阻塞响应式IO,单位时间内有限资源下支持更高的并发量。
    • 支持使用Java8 Lambda表达式函数。
    • 支持同步、异步、Stream流式传输。

    WebFlux使用

    maven依赖
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    
    WebClient实例创建
    • WebClient.create()
    @Test
    public void testCreate() {
        Mono<String> mono = WebClient
                //创建WenClient实例
                .create()
                //方法调用,WebClient中提供了多种方法
                .method(HttpMethod.GET)
                //请求url
                .uri("http://localhost:8080/hello")
                //获取响应结果
                .retrieve()
                //将结果转换为指定类型
                .bodyToMono(String.class);
        //block方法返回最终调用结果,block方法是阻塞的
        System.out.println("响应结果:" + mono.block());
    }
    
    • WebClient.create(String baseUrl):指定baseUrl,使用该客户端发送请求都是基于baseUrl。
    @Test
    public void testCreateBaseUrl() {
        Mono<String> mono = WebClient
                //创建WenClient实例,指定基础url,所以下面uri请求的路径都是基于这个路径
                .create("http://localhost:8080")
                //方法调用,WebClient中提供了多种方法
                .method(HttpMethod.GET)
                //请求url
                .uri("/hello")
                //获取响应结果
                .retrieve()
                //将结果转换为指定类型
                .bodyToMono(String.class);
        //block方法返回最终调用结果,block方法是阻塞的
        System.out.println("响应结果:" + mono.block());
    }
    
    • WebClient.builder():返回一个WebClient.Builder,该对象可以做链式调用,传递更多的参数。
    @Test
    public void testBuilder() {
        Mono<String> mono = WebClient
                .builder()
                //配置头信息,或者其他信息
                .defaultHeader("token", "123456789")
                //创建WebClient实例
                .build()
                //方法调用,WebClient中提供了多种方法
                .method(HttpMethod.GET)
                //请求url
                .uri("http://localhost:8080/hello")
                //获取响应结果
                .retrieve()
                //将结果转换为指定类型
                .bodyToMono(String.class);
    }
    
    支持的可选配置

    uriBuilderFactory:自定义UriBuilderFactory灵活配置使用Url
    defaultHeader:为HTTP请求设置Headers请求头
    defaultCookie:为HTTP请求设置Cookies
    defaultRequest:自定义HttpRequest
    filter:为HTTP请求增加客户端过滤器
    exchangeStrategies:HTTP读写信息自定义
    clientConnector:HTTP客户端连接器设置

    获取响应结果的方式

    block()阻塞式获取响应结果
    @Test
    public void testMono() {
        Mono<User> userMono = WebClient
                .create()
                .method(HttpMethod.GET)
                .uri("http://localhost:8080/hello")
                .retrieve()
                .bodyToMono(User.class);
        User user = userMono.block();
    }
    
    @Test
    public void testFlux() {
        Flux<User> userFlux = WebClient
                .create()
                .method(HttpMethod.GET)
                .uri("http://localhost:8080/hello")
                .retrieve()
                .bodyToFlux(User.class);
        List<User> users = userFlux.collectList().block();
    }
    

    使用Mono和Flux接收返回结果,一个Mono对象包含0个或1个元素,而一个Flux对象包含1个或多个元素。

    subscribe()非阻塞式获取响应结果
    @Test
    public void testSubscribe() {
        Mono<String> mono = WebClient
                .create()
                .method(HttpMethod.GET)
                .uri("http://localhost:8080/hello")
                .retrieve()
                .bodyToMono(String.class);
        mono.subscribe(WebClientTest::handleMonoResp);
    }
    //响应回调
    private static void handleMonoResp(String monoResp) {
        System.out.println("请求结果为:" + monoResp);
    }
    
    exchange()获取HTTP响应完整内容
    @Test
    public void testExchange() {
        Mono<ClientResponse> clientResponseMono = WebClient
                .create()
                .method(HttpMethod.GET)
                .uri("http://localhost:8080/hello")
                .exchange();
        ClientResponse clientResponse = clientResponseMono.block();
        //响应头
        ClientResponse.Headers headers = clientResponse.headers();
        //响应状态
        HttpStatus httpStatus = clientResponse.statusCode();
        //响应状态码
        int rawStatusCode = clientResponse.rawStatusCode();
        //响应体
        Mono<String> mono = clientResponse.bodyToMono(String.class);
        String body = mono.block();
    }
    

    占位符传参

    数字占位符
    public static void main(String[] args) throws Exception {
        List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        String url = "http://localhost:8080/user/{1}/{2}";
        Mono<String> mono = WebClient.create()
                .method(HttpMethod.POST)
                .uri(url, list.toArray())
                .retrieve()
                .bodyToMono(String.class);
        String result = mono.block();
    }
    
    参数名占位符
    public static void main(String[] args) throws Exception {
        String url = "http://localhost:8080/user/{id}/{name}";
        String id = "123";
        String name = "Boss";
        Mono<String> mono = WebClient.create()
                .method(HttpMethod.POST)
                .uri(url, id, name)
                .retrieve()
                .bodyToMono(String.class);
        String result = mono.block();
    }
    
    map传参
    public static void main(String[] args) throws Exception {
        String url = "http://localhost:8080/user/{id}/{name}";
        Map<String, String> params = new HashMap<>();
        params.put("id", "123");
        params.put("name", "Boss");
        Mono<String> mono = WebClient.create()
                .method(HttpMethod.POST)
                .uri(url, params)
                .retrieve()
                .bodyToMono(String.class);
        String result = mono.block();
    }
    

    博客内容仅供自已学习以及学习过程的记录,如有侵权,请联系我删除,谢谢!

    相关文章

      网友评论

          本文标题:Spring5之WebClient简单使用

          本文链接:https://www.haomeiwen.com/subject/yppjvktx.html