WebClient
is asynchronous/non-blocking HTTP Client, it is replacement of RestTemplate
, Here we walk through how to create and use webClient
.
Add Dependency
implementation 'org.springframework.boot:spring-boot-start-webflux'
The Steps for WebClient
to send request and receive response is following:
- Create
WebClient
instance - Attach
post
orget
method - Attach the
Header
section, usualcontent-type
and/orAuthorization
. - Attach the
body
section - Attach the
retrieve
orexchange
method if you want handle response - Attach
onStatus
to handle404
or500
error - Attach the
subscriber
to thebodyToXXX
method, the webFlux is asynchronous method, so we need subsriber to handle the object asychronously.
1. Create Instance of WebClient
1.1 Three ways to create WebClient instance
WebClient webClient = new WebClient.create();
or create with URL:
WebClient webClient = new WebClient.create("http://127.0.0.1/some_link");
or with builder
mode:
following define a content we will send is json
WebClient webClient = WebClient.builder()
.basheUrl("http://127.0.0.1/some_linke")
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
in the builder
mode, you can add defaulHeader
and other information to the WebClient.
1.2 Insert filter()
to log, modify the request and response
Inject ExchangeFilterFunction
during the building to intercept the request, you can use this functio to log the request or modify them:
with lambda version:
WebClient client = WebClient.builder()
.filter((request, next) -> {
logger.info("Request {} : {}", request.method(), request.url());
return next.exchange(request);
})
.build();
with method:
WebClient client = WebClient.builder()
.filter(logRequest())
.build();
private ExchangeFilterFunction logRequest(){
return (request, next) -> {
logger.info("Request {} : {}", request.method(), request.url());
return next.exchange(request);
};
}
If you want to modify the request, you need use ClientRequest
class to extract the request:
WebClient client = WebClient.builder()
.filter((request, next) -> {
ClientRequest filtered = ClientRequest.from(request)
.header("foo", "bar")
.build();
return next.exchange(filtered);
})
.build();
the above example show the intercept the request and add attribution to the header.
1.3 Intecept the response
use ofResponseProcessor()
factory pattern to create response filters:
WebClient client = WebClient.builder()
.filter( response -> {
logger.info("Response status {}", response.statusCode());
return mono.just(response);
}
.build();
2. Send Request by get()
or post()
use get()
or post()
to use different HTTP methods.
3. Attach header
You can define defaultHeader
when you create webClient, you also can attache the defaultHeader
after get()
or post()
method by use header()
method:
webClient.get()
.uri("")
.header("Authorization", "Basic " + Base64Utils
.encodeToString((username + ":" + token).getBytes(UTF_8)))
This insert a token in the header for authorization.
4. Attach body
4.1 Type of Request/Response Body
WebFlux is part of Project Reactor
, it is non-blocking, asynchronous framework. Since it is Asychronous, so response back from Server could be 0, 1 till n. So Spring WebFlux provide following 2 type of object to wrap the response:
Mono<T>
which can be either return 0..1 response(s).Flux<T>
which can be return 0..n response(s).
so if your service return 1 object, then use Mono<T>
, if return List
, then use Flux<T>
To send Mono<T>
request body:
webClient.post().uri("").body(Mono.just(OBJECT_INSTANCE_VARIABLE), YOUR_OBJECT.class)
put your object instance in the just
method and determine the class of your object.
To receive Mono<T>
response body:
webClient.post().uri("").body(Mono.just(OBJECT_INSTANCE_VARIABLE), YOUR_OBJECT.class).retrieve().bodyToMono(YOUR_RESPONSE_OBJECT.class)
retrieve()
is the method to handle response, and after retreive, we use bodyToMono
method
4.2 Three ways to define body
a. use .body()
webClient.post().uri("").body(Mono.just(OBJECT_INSTANCE_VARIABLE), YOUR_OBJECT.class)
This is normal way.
b. use syncBody()
(Deprecated)
This is shortcut version of body()
, if you just have 1 object to send, you can use following format:
webClient.post().uri("").syncBody(OBJECT_INSTANCE_VARIABLE)
c. use BodyInserteres
class to create BodyInserter
and then pass it in body()
, this is for those FormData
, MultipartData
(file upload) those special.
5. Handle Response by retrieve()
or exchange()
After you send the request to server, you need to see the response, there are 2 ways to handle: retrieve()
is simpler, if you want to more control on response, then you can use exchange()
method. exchange()
provide full access to repsonse’s headers and body.