spring 5 webclient使用指南

栏目: Java · 发布时间: 8年前

内容简介:spring 5 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:{},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的,非常值得使用。

doc


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Mobilizing Web Sites

Mobilizing Web Sites

Layon, Kristofer / 2011-12 / 266.00元

Everyone has been talking about the mobile web in recent years, and more of us are browsing the web on smartphones and similar devices than ever before. But most of what we are viewing has not yet bee......一起来看看 《Mobilizing Web Sites》 这本书的介绍吧!

html转js在线工具
html转js在线工具

html转js在线工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具