WebClient HTTP 请求编码模板

一、WebClient

1、概述
  • WebClient 是 WebFlux 模块的一部分,专门用于发送 HTTP 请求和处理 HTTP 响应
2、WebClient 引入
  • pom.xml,引入依赖,这里是 Spring Boot 项目中引入,通常不需要显式指定版本号
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webfluxartifactId>
dependency>

二、WebClient 基本使用

1、普通 GET 请求
(1)Server
@GetMapping("/testGet")
public String testGet() {
    return "testGet Hello World";
}
(2)client
WebClient webClient = WebClient.create();

Mono<String> response = webClient.get()
        .uri("http://127.0.0.1:9999/test/testGet")
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
  • 输出结果
请求成功,结果为:testGet Hello World
2、普通带参 GET 请求
(1)Server
@GetMapping("/testGetCarryData")
public String testGetCarryData(@RequestParam("str") String str) {
    return "testGetCarryData " + str;
}
(2)Client
WebClient webClient = WebClient.create();

Mono<String> response = webClient.get()
        .uri("http://127.0.0.1:9999/test/testGetCarryData?str=12345")
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
WebClient webClient = WebClient.create("http://127.0.0.1:9999");

Mono<String> response = webClient.get()
        .uri(
                uriBuilder ->
                        uriBuilder.path("/test/testGetCarryData")
                                .queryParam("str", "12345")
                                .build()
        )
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
请求成功,结果为:testGetCarryData 12345
3、RESTFul GET 请求
(1)Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
    private int id;
    private String name;
    private int age;
}
(2)Server
@GetMapping("/testRestful/{id}")
public User testGetRestful(@PathVariable Integer id) {
    HashMap<Integer, User> userMap = new HashMap<>();
    userMap.put(1, new User(1, "jack", 10));
    userMap.put(2, new User(2, "tom", 20));
    userMap.put(3, new User(3, "smith", 30));

    return userMap.get(id);
}
(3)Client
WebClient webClient = WebClient.create();

Mono<User> response = webClient.get()
        .uri("http://127.0.0.1:9999/test/testGetRestful/{id}", 1)
        .retrieve()
        .bodyToMono(User.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
  • 输出结果
请求成功,结果为:User(id=1, name=jack, age=10)
4、普通 POST 请求
(1)Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
class User {
    private int id;
    private String name;
    private int age;
}
(2)Server
@PostMapping("/testPost")
public User testPost(@RequestBody User user) {
    HashMap<Integer, User> userMap = new HashMap<>();
    userMap.put(1, new User(1, "jack", 10));
    userMap.put(2, new User(2, "tom", 20));
    userMap.put(3, new User(3, "smith", 30));

    return userMap.get(user.getId());
}
(3)Client
User user = new User();
user.setId(1);

WebClient webClient = WebClient.create();

Mono<String> response = webClient.post()
        .uri("http://127.0.0.1:9999/test/testPost")
        .contentType(MediaType.APPLICATION_JSON)
        .body(BodyInserters.fromValue(user))
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
  • 输出结果
请求成功,结果为:{"id":1,"name":"jack","age":10}

三、WebClient 异常请求

1、404 请求
WebClient webClient = WebClient.create();

Mono<String> response = webClient.get()
        .uri("http://127.0.0.1:9999/test/testGet12345")
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println(throwable instanceof WebClientResponseException.NotFound);
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
  • 输出结果
true
请求失败,结果为:404 Not Found from GET http://127.0.0.1:9999/test/testGet12345
2、超时请求
(1)Server
@GetMapping("/testTimeout")
public String testTimeout() {
    try {
        Thread.sleep(20 * 1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "testTimeout Hello World";
}
(2)Client
// 创建自定义的 HttpClient,并设置连接超时和响应超时
HttpClient httpClient = HttpClient.create()
        .responseTimeout(Duration.ofSeconds(5)) // 设置响应超时为 15 秒
        .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000); // 设置连接超时为 3 秒

// 使用自定义的 HttpClient 创建 WebClient
WebClient webClient = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .baseUrl("http://127.0.0.1:9999") // 设置基础 URL
        .build();

Mono<String> response = webClient.get()
        .uri("/test/testTimeout")
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
  • 输出结果
io.netty.handler.timeout.ReadTimeoutException: null

请求失败,结果为:null

四、WebClient 扩展

1、下载图片
(1)Server
  • application.yaml
server:
  port: 9999
spring:
  mvc:
    static-path-pattern: /file/download/**
  web:
    resources:
      static-locations: file:D:/fileUpload/
(2)Client
WebClient webClient = WebClient.create();

Mono<byte[]> response = webClient.get()
        .uri("http://127.0.0.1:9999/file/download/1.png")
        .accept(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG)
        .retrieve()
        .bodyToFlux(DataBuffer.class)
        .reduce(new ByteArrayOutputStream(), (baos, dataBuffer) -> {
            try {
                byte[] bytes = new byte[dataBuffer.readableByteCount()];
                dataBuffer.read(bytes);
                baos.write(bytes);
                DataBufferUtils.release(dataBuffer);
            } catch (IOException e) {
                e.printStackTrace();
                DataBufferUtils.release(dataBuffer);
                return null;
            }
            return baos;
        })
        .map(byteArrayOutputStream -> {
            if (byteArrayOutputStream == null) return null;
            return byteArrayOutputStream.toByteArray();
        });

response.subscribe(result -> {
    System.out.println("请求成功");
    if (result != null) System.out.println("result length is " + result.length);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
int size = 10 * 1024 * 1024;
ExchangeStrategies strategies = ExchangeStrategies.builder()
        .codecs(codecs -> codecs.defaultCodecs().maxInMemorySize(size))
        .build();

WebClient webClient = WebClient.builder()
        .exchangeStrategies(strategies)
        .build();

Mono<byte[]> response = webClient.get()
        .uri("http://127.0.0.1:9999/file/download/1.png")
        .accept(MediaType.IMAGE_JPEG, MediaType.IMAGE_PNG)
        .retrieve()
        .bodyToMono(byte[].class);

response.subscribe(result -> {
    System.out.println("请求成功");
    if (result != null) System.out.println("result length is " + result.length);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
  • 输出结果
请求成功
result length is 846049
2、携带请求头
(1)Server
@GetMapping("/testRequestHeader")
public String testRequestHeader(HttpServletRequest request) {
    String test = request.getHeader("test");
    return "testRequestHeader " + test;
}
(2)Client
WebClient webClient = WebClient.builder()
        .baseUrl("http://127.0.0.1:9999")
        .filter((request, next) -> {

            // 创建一个新的 ClientRequest,其中包含修改后的 headers
            ClientRequest mutatedRequest = ClientRequest.from(request)
                    .header("test", "Hello World 123")
                    .build();

            // 使用修改后的请求继续执行请求链
            return next.exchange(mutatedRequest);
        })
        .build();

Mono<String> response = webClient.get()
        .uri("/test/testRequestHeader")
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
WebClient webClient = WebClient.create();

Mono<String> response = webClient.get()
        .uri("http://127.0.0.1:9999/test/testRequestHeader")
        .header("test", "Hello World 123")
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
  • 输出结果
请求成功,结果为:testRequestHeader Hello World 123
3、请求头扩展
  1. 获取请求方式
String httpMethod = request.method().name().toUpperCase();
  1. 打印出所有请求头信息
HttpHeaders headers = request.headers();
headers.forEach((key, values) -> {
    values.forEach(value -> System.out.println(key + ": " + value));
});
  1. 获取 url,例如,https://127.0.0.1:12345/personList 就获取这部分 /personList
String url = request.url().getRawPath();
4、处理响应头
(1)Server
@GetMapping("/testResponseHeader")
public ResponseEntity<String> testResponseHeader() {
    HttpHeaders headers = new HttpHeaders();
    headers.add("test", "Hello World 123");
    return new ResponseEntity<String>("testResponseHeader: Hello World", headers, HttpStatus.OK);
}
(2)Client
WebClient webClient = WebClient.builder()
        .filter((clientRequest, next) -> {
            return next.exchange(clientRequest).flatMap(clientResponse -> {
                clientResponse.headers().asHttpHeaders().forEach((name, values) -> {
                    values.forEach(value -> System.out.println(name + ": " + value));
                });
                return Mono.just(clientResponse);
            });
        })
        .build();

Mono<String> response = webClient.get()
        .uri("http://127.0.0.1:9999/test/testResponseHeader")
        .retrieve()
        .bodyToMono(String.class);

response.subscribe(result -> {
    System.out.println("请求成功,结果为:" + result);
}, throwable -> {
    System.out.println("请求失败,结果为:" + throwable.getMessage());
});
  • 输出结果
test: Hello World 123
Content-Type: text/plain;charset=UTF-8
Content-Length: 30
Date: Wed, 21 Aug 2024 12:21:20 GMT
请求成功,结果为:testResponseHeader Hello World

你可能感兴趣的:(后端,-,Java,-,Spring,Boot,http,网络协议,网络,java,spring,boot)