首页 > 开发 > Java > 正文

spring5 webclient使用指南详解

2024-07-13 10:17:04
字体:
来源:转载
供稿:网友

之前写了一篇restTemplate使用实例,由于50.html">spring 5全面引入reactive,同时也有了restTemplate的reactive版webclient,本文就来对应展示下webclient的基本使用。

请求携带header

携带cookie

@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

@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

@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传递参数

@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传递参数

@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表单

@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

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

@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二进制--上传文件

@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());  }

下载二进制

下载图片

@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"));  }

下载文件

@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());  }

错误处理

@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);  }
  1. 可以使用onStatus根据status code进行异常适配
  2. 可以使用doOnError异常适配
  3. 可以使用onErrorReturn返回默认值

小结

webclient是新一代的async rest template,api也相对简洁,而且是reactive的,非常值得使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VeVb武林网。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表