之前写了一篇restTemplate使用实例,由于spring 5全面引入reactive,同时也有了restTemplate的reactive版webclient,本文就来对应展示下webclient的基本使用。
请求携带header
携带cookie
1
2
3
4
5
6
7
8
9
10
11
|
@Test public void testWithCookie(){ Mono<String> resp = WebClient.create() .method(HttpMethod.GET) .uri( "http://baidu.com" ) .cookie( "token" , "xxxx" ) .cookie( "JSESSIONID" , "XXXX" ) .retrieve() .bodyToMono(String. class ); LOGGER.info( "result:{}" ,resp.block()); } |
携带basic auth
1
2
3
4
5
6
7
8
9
10
11
12
|
@Test public void testWithBasicAuth(){ String basicAuth = "Basic " + Base64.getEncoder().encodeToString( "user:pwd" .getBytes(StandardCharsets.UTF_8)); LOGGER.info(basicAuth); Mono<String> resp = WebClient.create() .get() .uri( "http://baidu.com" ) .header(HttpHeaders.AUTHORIZATION,basicAuth) .retrieve() .bodyToMono(String. class ); LOGGER.info( "result:{}" ,resp.block()); } |
设置全局user-agent
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@Test public void testWithHeaderFilter(){ WebClient webClient = WebClient.builder() .defaultHeader(HttpHeaders.USER_AGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36" ) .filter(ExchangeFilterFunctions .basicAuthentication( "user" , "password" )) .filter((clientRequest, next) -> { LOGGER.info( "Request: {} {}" , clientRequest.method(), clientRequest.url()); clientRequest.headers() .forEach((name, values) -> values.forEach(value -> LOGGER.info( "{}={}" , name, value))); return next.exchange(clientRequest); }) .build(); Mono<String> resp = webClient.get() .uri( "https://baidu.com" ) .retrieve() .bodyToMono(String. class ); LOGGER.info( "result:{}" ,resp.block()); } |
get请求
使用placeholder传递参数
1
2
3
4
5
6
7
8
9
10
11
|
@Test public void testUrlPlaceholder(){ Mono<String> resp = WebClient.create() .get() //多个参数也可以直接放到map中,参数名与placeholder对应上即可 .uri( "http://www.baidu.com/s?wd={key}&other={another}" , "北京天气" , "test" ) //使用占位符 .retrieve() .bodyToMono(String. class ); LOGGER.info( "result:{}" ,resp.block()); } |
使用uriBuilder传递参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Test public void testUrlBiulder(){ Mono<String> resp = WebClient.create() .get() .uri(uriBuilder -> uriBuilder .scheme( "http" ) .host( "www.baidu.com" ) .path( "/s" ) .queryParam( "wd" , "北京天气" ) .queryParam( "other" , "test" ) .build()) .retrieve() .bodyToMono(String. class ); LOGGER.info( "result:{}" ,resp.block()); } |
post表单
1
2
3
4
5
6
7
8
9
10
11
12
|
@Test public void testFormParam(){ MultiValueMap<String, String> formData = new LinkedMultiValueMap<>(); formData.add( "name1" , "value1" ); formData.add( "name2" , "value2" ); Mono<String> resp = WebClient.create().post() .uri( "http://www.w3school.com.cn/test/demo_form.asp" ) .contentType(MediaType.APPLICATION_FORM_URLENCODED) .body(BodyInserters.fromFormData(formData)) .retrieve().bodyToMono(String. class ); LOGGER.info( "result:{}" ,resp.block()); } |
post json
使用bean来post
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
static class Book { String name; String title; public String getName() { return name; } public void setName(String name) { this .name = name; } public String getTitle() { return title; } public void setTitle(String title) { this .title = title; } } @Test public void testPostJson(){ Book book = new Book(); book.setName( "name" ); book.setTitle( "this is title" ); Mono<String> resp = WebClient.create().post() .uri( "http://localhost:8080/demo/json" ) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(Mono.just(book),Book. class ) .retrieve().bodyToMono(String. class ); LOGGER.info( "result:{}" ,resp.block()); } |
直接post raw json
1
2
3
4
5
6
7
8
9
10
11
12
|
@Test public void testPostRawJson(){ Mono<String> resp = WebClient.create().post() .uri( "http://localhost:8080/demo/json" ) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(BodyInserters.fromObject( "{\n" + " \"title\" : \"this is title\",\n" + " \"author\" : \"this is author\"\n" + "}" )) .retrieve().bodyToMono(String. class ); LOGGER.info( "result:{}" ,resp.block()); } |
post二进制--上传文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@Test public void testUploadFile(){ HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.IMAGE_PNG); HttpEntity<ClassPathResource> entity = new HttpEntity<>( new ClassPathResource( "parallel.png" ), headers); MultiValueMap<String, Object> parts = new LinkedMultiValueMap<>(); parts.add( "file" , entity); Mono<String> resp = WebClient.create().post() .uri( "http://localhost:8080/upload" ) .contentType(MediaType.MULTIPART_FORM_DATA) .body(BodyInserters.fromMultipartData(parts)) .retrieve().bodyToMono(String. class ); LOGGER.info( "result:{}" ,resp.block()); } |
下载二进制
下载图片
1
2
3
4
5
6
7
8
9
10
11
|
@Test public void testDownloadImage() throws IOException { Mono<Resource> resp = WebClient.create().get() .uri( "http://www.toolip.gr/captcha?complexity=99&size=60&length=9" ) .accept(MediaType.IMAGE_PNG) .retrieve().bodyToMono(Resource. class ); Resource resource = resp.block(); BufferedImage bufferedImage = ImageIO.read(resource.getInputStream()); ImageIO.write(bufferedImage, "png" , new File( "captcha.png" )); } |
下载文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
@Test public void testDownloadFile() throws IOException { Mono<ClientResponse> resp = WebClient.create().get() .uri( "http://localhost:8080/file/download" ) .accept(MediaType.APPLICATION_OCTET_STREAM) .exchange(); ClientResponse response = resp.block(); String disposition = response.headers().asHttpHeaders().getFirst(HttpHeaders.CONTENT_DISPOSITION); String fileName = disposition.substring(disposition.indexOf( "=" )+ 1 ); Resource resource = response.bodyToMono(Resource. class ).block(); File out = new File(fileName); FileUtils.copyInputStreamToFile(resource.getInputStream(),out); LOGGER.info(out.getAbsolutePath()); } |
错误处理
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
@Test public void testRetrieve4xx(){ WebClient webClient = WebClient.builder() .baseUrl( "https://api.github.com" ) .defaultHeader(HttpHeaders.CONTENT_TYPE, "application/vnd.github.v3+json" ) .defaultHeader(HttpHeaders.USER_AGENT, "Spring 5 WebClient" ) .build(); WebClient.ResponseSpec responseSpec = webClient.method(HttpMethod.GET) .uri( "/user/repos?sort={sortField}&direction={sortDirection}" , "updated" , "desc" ) .retrieve(); Mono<String> mono = responseSpec .onStatus(e -> e.is4xxClientError(),resp -> { LOGGER.error( "error:{},msg:{}" ,resp.statusCode().value(),resp.statusCode().getReasonPhrase()); return Mono.error( new RuntimeException(resp.statusCode().value() + " : " + resp.statusCode().getReasonPhrase())); }) .bodyToMono(String. class ) .doOnError(WebClientResponseException. class , err -> { LOGGER.info( "ERROR status:{},msg:{}" ,err.getRawStatusCode(),err.getResponseBodyAsString()); throw new RuntimeException(err.getMessage()); }) .onErrorReturn( "fallback" ); String result = mono.block(); LOGGER.info( "result:{}" ,result); } |
- 可以使用onStatus根据status code进行异常适配
- 可以使用doOnError异常适配
- 可以使用onErrorReturn返回默认值
小结
webclient是新一代的async rest template,api也相对简洁,而且是reactive的,非常值得使用。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://juejin.im/post/5a62f17cf265da3e51333205