Springboot : How to use WebClient instead of RestTemplate for Performing Non blocking and Asynchronous calls

前端 未结 3 1955
无人及你
无人及你 2021-02-15 01:18

I have a springboot project which uses Springboot Resttemplate. We have moved to springboot 2.0.1 from 1.5.3 and we are trying to make the rest calls from it asynchronous by us

3条回答
  •  灰色年华
    2021-02-15 01:41

    The first thing to understand is if you are needing to call .block() you might as well stick with RestTemplate, using WebClient will gain you nothing.

    You need to start thinking in reactive terms if you want to gain from using WebClient. A reactive process is really just a sequence of steps, the input of each step being the output of the step before it. When a request comes in, your code creates the sequence of steps and returns immediately releasing the http thread. The framework then uses a pool of worker threads to execute each step when the input from the previous step becomes available.

    The benefit is a huge gain in capacity to accept competing requests at the small cost of having to rethink the way you write code. Your application will only need a very small pool of http threads and another very small pool of worker threads.

    When your controller method is returning a Mono or Flux, you have got it right and there will be no need to call block().

    Something like this in it's simplest form:

    @GetMapping(value = "endpoint", produces = MediaType.TEXT_PLAIN_VALUE)
    @ResponseBody
    @ResponseStatus(OK)
    public Mono controllerMethod() {
    
        final UriComponentsBuilder builder =
                UriComponentsBuilder.fromHttpUrl("http://base.url/" + "endpoint")
                        .queryParam("param1", "value");
    
        return webClient
                .get()
                .uri(builder.build().encode().toUri())
                .accept(APPLICATION_JSON_UTF8)
                .retrieve()
                .bodyToMono(String.class)
                .retry(4)
                .doOnError(e -> LOG.error("Boom!", e))
                .map(s -> {
    
                    // This is your transformation step. 
                    // Map is synchronous so will run in the thread that processed the response. 
                    // Alternatively use flatMap (asynchronous) if the step will be long running. 
                    // For example, if it needs to make a call out to the database to do the transformation.
    
                    return s.toLowerCase();
                });
    }
    

    Moving to thinking in reactive is a pretty big paradigm shift, but well worth the effort. Hang in there, it's really not that difficult once you can wrap your head around having no blocking code at all in your entire application. Build the steps and return them. Then let the framework manage the executions of the steps.

    Happy to provide more guidance if any of this is not clear.

    Remember to have fun :)

提交回复
热议问题