web编程(4) WebClient

1. 概述

WebClient是Spring WebFlux提供用于http请求的客户端类,它完全非阻塞,等待远程响应的同时,不会阻塞本地正在执行的线程,单位时间内有限资源下支持更高的并发量。

 2. 配置

2.1 构建

create方式(默认参数)

		WebClient client1 = WebClient.create();
		WebClient client2 = WebClient.create("http://192.168.0.108:8082");

builder方式(可调整、补充WebClient的默认参数)

		WebClient client = WebClient.builder()
				.baseUrl("http://192.168.0.108:8082")
				.defaultHeaders( x -> {
					x.add("aa", "11");
				})				
				//.clientConnector(new ReactorClientHttpConnector())
				.build();

WebClient中的参数,往往作为所有请求的通用配置,默认HTTP客户端配置的是reactor netty。

2.2 缓存区

请求数据包较大时,需要调整 编解码缓冲区大小,以免出现超限异常,默认情况下,这些限制被设置为256KB。

		WebClient webClient = WebClient.builder()
		        .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(2 * 1024 * 1024))
		        .build();

2.3 超时

连接超时

		HttpClient httpClient = HttpClient.create()
		        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);

		WebClient webClient = WebClient.builder()
		        .clientConnector(new ReactorClientHttpConnector(httpClient))
		        .build();

读写超时

		HttpClient httpClient = HttpClient.create()
		        .doOnConnected(conn -> conn
		                .addHandlerLast(new ReadTimeoutHandler(10))
		                .addHandlerLast(new WriteTimeoutHandler(10)));

		WebClient webClient = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .build();

响应超时(通用)

		HttpClient httpClient = HttpClient.create()
		        .responseTimeout(Duration.ofSeconds(2));

		WebClient webClient = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .build();

响应超时(单独)

		WebClient.create().get()
        .uri("https://example.org/path")
        .httpRequest(httpRequest -> {
            HttpClientRequest reactorRequest = httpRequest.getNativeRequest();
            reactorRequest.responseTimeout(Duration.ofSeconds(2));
        })
        .retrieve()
        .bodyToMono(String.class);

3. 实践

3.1 get请求

		WebClient client = WebClient.create("http://192.168.0.108:8082");
		
		Mono<Apple> result = client.get()
				.uri("/demo/getInfo?id=1")
				.accept(MediaType.APPLICATION_JSON)
		        .retrieve()
		        .bodyToMono(Apple.class);

		// 订阅结果
		result.subscribe(System.out::println);	

3.2 post请求

		WebClient client = WebClient.create("http://192.168.0.108:8082");
		Mono<Apple> body = Mono.just(new Apple(1, "xxx"));
		
		Mono<String> result = client.post()
				.uri("/demo/postInfo")
				.contentType(MediaType.APPLICATION_JSON)
				.body(body, Apple.class)
		        .retrieve()
		        .bodyToMono(String.class);
		
		// 订阅结果
		result.subscribe(System.out::println);

3.3 retrieve获取响应

通过retrieve方式获取响应,可按返回值类型,直接获取结果,上面例子都是该种方式。

3.4 exchange获取响应

通过exchange方式,能获取更多响应细节数据,依据这些数据,可以做个性化的响应处理。

		WebClient client = WebClient.create("http://192.168.0.108:8082");
		
		Mono<Apple> result = client.get()
				.uri("/demo/getInfo?aa=1")
				.accept(MediaType.APPLICATION_JSON)
				.exchangeToMono(res -> {
					
					// 获取 statusCode, headers
					System.out.println("statusCode: " + res.statusCode());
					res.headers().asHttpHeaders()
					.forEach((k, v) -> {
						System.out.println(String.format("header, %s: %s", k, v));
					});
										
					return res.bodyToMono(Apple.class);
				});

		// 订阅结果
		result.subscribe(System.out::println);	

3.5 阻塞

block方法,可以同步阻塞方式获取结果。

		WebClient client = WebClient.create("http://192.168.0.108:8082");
		
		Apple result = client.get()
				.uri("/demo2/getInfo?id=1")
				.accept(MediaType.APPLICATION_JSON)
		        .retrieve()
		        .bodyToMono(Apple.class)
		        .block();

		// 结果
		System.out.println(result);

3.6 上下文

WebClient采用异步非阻塞方式,来处理请求、响应,可以通过上下文功能,在贯穿一个请求的整个过程共享该数据,样例如下:

		WebClient client = WebClient.create("http://192.168.0.108:8082");
		
		Mono<Apple> result = client.get()
				.uri("/demo/getInfo?id=1")
				.accept(MediaType.APPLICATION_JSON)
		        .retrieve()
		        .bodyToMono(Apple.class)
		        .flatMap(x -> {		        	
		        	return Mono.deferContextual(context -> {		        		
		        		x.setName(context.get("aa") + x.getName());		        		
		        		return Mono.just(x);
		        	});
		        })		        
		        .contextWrite(context -> context.put("aa", "xxx-"));

		// 订阅结果
		result.subscribe(System.out::println);	

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值