RestTemplate、WebClient与HttpInterface

RestTemplate、WebClient与HttpInterface

SpringBoot integrates many lightweight HTTP clients
  • RestTemplate:General development
  • WebClient: Responsive programming development
  • HttpInterface: Declarative Programming
Introduction to reactive programming

Reactive Programming is a programming paradigm used for 处理异步数据流and 事件流. It is based on the concepts of programming 观察者模式and 函数式processing data changes and interactions by using streams or events.

In reactive programming, the data stream is viewed as a continuous time series, and the program can subscribe to this data stream and handle changes in the data accordingly. When data changes, the program automatically updates related operations without manual intervention.

Reactive programming has the following characteristics:

  • Responsive: Ability to respond promptly to changes in the data flow without manual triggering.

  • Asynchronous: Ability to handle asynchronous operations such as network requests or user interactions.

  • Delayed execution: Relevant operations are only performed when the results are actually needed .

  • Composability: Ability to combine multiple operations to form complex data flow processing logic.

  • Error handling: Ability to handle exceptions and errors and provide corresponding handling mechanisms.

Reactive programming has advantages in many scenarios, such as user interface responsiveness, data flow processing and analysis, etc.

The difference between RestTemplate and WebClient

RestTemplate runs in a synchronous blocking manner, and WebClient runs in an asynchronous, non-blocking manner. Only the corresponding method will be executed when the result returned by WebClient is required.

Using WebClient

Introduce dependencies

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

Build the business

@Service
public class CityServiceImpl implements CityService {
    
    
    @Override
    public Mono<String> query(String city) {
    
    
        WebClient webClient = WebClient.create();
        Map<String, String> param = new HashMap<>();
        param.put("city", "西安");
        return webClient.get()
                .uri("https://wttr.in/{city}?lang=zh", param)
                .accept(MediaType.ALL)
                .retrieve()
                .bodyToMono(String.class);
       
    }
}
package com.vmware.controller;

import com.vmware.service.CityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;

@RequestMapping("/city")
@RestController
public class CityController {
    
    
    @Autowired
    private CityService cityService;
    @GetMapping("/{city}")
    public Mono<String> city(@PathVariable String city) throws InterruptedException {
    
    
        Mono<String> mono = cityService.query(city);
        return query;
    }
}

  • Note: Before the mono object is returned, the interface is actually in an uncalled state, and the call is delayed after returning.
HttpInterface

Introduction: HttpInterfaces is a new http calling method introduced by spring 6.0. It calls http requests by declaring interfaces. It is different from the traditional hard-coded method and relies onspring-boot-starter-webflux

Basic usage

package com.vmware.service;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.service.annotation.GetExchange;
import reactor.core.publisher.Mono;

public interface CityWebClientService {
    
    
    @GetExchange(url = "https://wttr.in/{city}?lang=zh")
    Mono<String> getWeather(@PathVariable String city);
}
@Override
    public Mono<String> queryByWebClient(String city) {
    
    
        WebClient client = WebClient.builder()
                .baseUrl("https://wttr.in")
                .codecs(clientCodecConfigurer -> {
    
    
                    clientCodecConfigurer.defaultCodecs()
                            .maxInMemorySize(256 * 1024 * 1024);//修改默认的buffer大小
                })
                .build();
        //创建工厂
        HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
        //创建代理对象
        CityWebClientService service = factory.createClient(CityWebClientService.class);
        return service.getWeather(city);
    }

Engineering use

  • Inject WebClientand HttpServiceProxyFactoryuse configuration classes into the container
  • Proxy the corresponding WebClient request interface and inject it into the container.
  • Inject the WebClient request interface into the corresponding business
package com.vmware.config;

import com.vmware.service.CityWebClientService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.support.WebClientAdapter;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;

@Configuration
public class WebClientConfig {
    
    
    /**
     * @apiNote 配置WebClient
     * @return
     */
    @Bean
    public WebClient httpServiceProxyFactory() {
    
    
        return WebClient.builder()
                .codecs(clientCodecConfigurer -> {
    
    
                    clientCodecConfigurer.defaultCodecs()
                            .maxInMemorySize(256 * 1024 * 1024);//修改默认的buffer大小
                })
                .build();
    }

    /**
     * @apiNote 构建 HttpServiceProxyFactory
     * @param client
     * @return
     */
    @Bean
    public HttpServiceProxyFactory factory(WebClient client) {
    
    
        //创建工厂
        return HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
    }

    /**
     * @apiNote 代理HttpClient接口
     * @param factory
     * @return
     */
    @Bean
    public CityWebClientService cityWebClientService(HttpServiceProxyFactory factory) {
    
    
        return factory.createClient(CityWebClientService.class);
    }
}
package com.vmware.service.impl;

import com.vmware.service.CityService;
import com.vmware.service.CityWebClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.support.WebClientAdapter;
import org.springframework.web.service.invoker.HttpServiceProxyFactory;
import reactor.core.publisher.Mono;

import java.util.HashMap;
import java.util.Map;

@Service
public class CityServiceImpl implements CityService {
    
    
    @Autowired
    private CityWebClientService cityWebClientService;

    @Override
    public Mono<String> queryByWebClient2(String city) {
    
    
        return cityWebClientService.getWeather(city);
    }
}

おすすめ

転載: blog.csdn.net/qq_52751442/article/details/132055093