RestTemplate、WebClient与HttpInterface

RestTemplate、WebClient与HttpInterface

SpringBoot中集成了很多轻量级的Http客户端
  • RestTemplate:普通开发
  • WebClient:响应式编程开发
  • HttpInterface:声明式编程
响应式编程介绍

响应式编程(Reactive Programming)是一种编程范式,用于处理异步数据流事件流。它基于观察者模式函数式编程的概念,通过使用流(Stream)或者事件(Event)来处理数据的变化和交互。

在响应式编程中,数据流被看作是一个连续的时间序列,程序可以订阅这个数据流,并对数据的变化做出相应的处理。当数据发生变化时,程序会自动更新相关的操作,而无需手动干预。

响应式编程具有以下特点:

  • 响应式:能够对数据流中的变化做出及时响应,而无需手动触发。

  • 异步:能够处理异步操作,如网络请求或用户交互。

  • 延迟执行:只有在真正需要结果时才会执行相关操作

  • 可组合性:能够将多个操作组合在一起,形成复杂的数据流处理逻辑。

  • 错误处理:能够处理异常和错误,并提供相应的处理机制。

响应式编程在很多场景下都具有优势,例如用户界面的响应性、数据流的处理和分析等。

RestTemplate与WebClient区别

RestTemplate采用同步阻塞的方式运行,WebClient采用异步非阻塞的方式运行,只用需要WebClient返会的结果时对应的方法才会执行

使用WebClient

引入依赖

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

构建业务

@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;
    }
}

  • 注意:mono对象被返回之前实际上接口处于未调用状态,当返回后延时调用
HttpInterface

介绍:HttpInterfaces是由spring6.0引入的新的http调用方式,通过声明接口的方式对http请求进行调用,与传统硬编码的方法有所不同,依赖于spring-boot-starter-webflux

基本使用

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);
    }

工程化使用

  • WebClientHttpServiceProxyFactory使用配置类注入到容器中
  • 将对应的WebClient请求接口代理后注入到容器中
  • 在对应的业务中进行注入WebClient请求接口
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