加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

spring5 webclient使用指南详解

发布时间:2020-12-14 20:05:51 所属栏目:Java 来源:网络整理
导读:之前写了一篇restTemplate使用实例,由于spring 5全面引入reactive,同时也有了restTemplate的reactive版webclient,本文就来对应展示下webclient的基本使用。 请求携带header 携带cookie @Test public void testWithCookie(){ MonoString resp = WebClient.

之前写了一篇restTemplate使用实例,由于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:{},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的,非常值得使用。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

您可能感兴趣的文章:

  • spring-cloud入门之eureka-client(服务注册)
  • spring boot封装HttpClient的示例代码
  • spring boot整合CAS Client实现单点登陆验证的示例

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读