之前写了一篇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