Summary of RestTemplate and WebClient calling third-party interfaces


title: Summary of RestTemplate and WebClient calling third-party interfaces
date: 2023-01-31 16:51:29
tags:

  • Development technology and framework
    categories:
  • Development technology and framework
    cover: https://cover.png
    feature: false

1. RestTemplate

1.1 Introducing dependencies

RestTemplate is under the spring-boot-starter-web package

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

1.2 Configuration class

Inject RestTemplate and configure connection time etc.

@Configuration
public class RestTemplateConfig {
    
    

    @Bean
    public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
    
    
        return new RestTemplate(factory);
    }

    @Bean
    public ClientHttpRequestFactory simpleClientHttpRequestFactory() {
    
    
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(15000);
        factory.setReadTimeout(5000);

        return factory;
    }
}

1.3 Tools

RestTemplate is very simple to use. Here, the GET method and POST method are encapsulated into a tool class. The DELETE and PUT methods are used in the same way, as follows:

@Component
public class RestTemplateUtil {
    
    

    private static RestTemplate restTemplate;

    @Resource
    private void setRestTemplate(RestTemplate restTemplate) {
    
    
        RestTemplateUtil.staticSetRestTemplate(restTemplate);
    }

    /**
     * 静态注入方法, 解决多线程下可能出现的并发问题
     *
     * @param restTemplate RestTemplate
     * @author Fan
     * @since 2023/1/13 17:24
     */
    private static synchronized void staticSetRestTemplate(RestTemplate restTemplate) {
    
    
        RestTemplateUtil.restTemplate = restTemplate;
    }

    /**
     * 以 Get 方式请求第三方接口, getForEntity, 默认返回类型 String
     *
     * @param url 请求地址
     * @return {@link String}
     * @author Fan
     * @since 2023/1/13 16:18
     */
    public static String doGetWithEntity(String url) {
    
    
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);

        return responseEntity.getBody();
    }

    /**
     * 以 Get 方式请求第三方接口, getForEntity, 指定返回类型
     *
     * @param url   请求地址
     * @param clazz 返回类型
     * @return {@link T}
     * @author Fan
     * @since 2023/1/13 17:08
     */
    public static <T> T doGetWithEntity(String url, Class<T> clazz) {
    
    
        ResponseEntity<T> responseEntity = restTemplate.getForEntity(url, clazz);

        return responseEntity.getBody();
    }

    /**
     * 以 Get 方式请求第三方接口, getForObject, 返回值返回的是响应体, 省了再去 getBody(), 默认返回类型 String
     *
     * @param url 请求地址
     * @return {@link String}
     * @author Fan
     * @since 2023/1/13 16:19
     */
    public static String doGetWithObject(String url) {
    
    
        return restTemplate.getForObject(url, String.class);
    }

    /**
     * 以 Get 方式请求第三方接口, getForObject, 返回值返回的是响应体, 省了再去 getBody(), 指定返回类型
     *
     * @param url   请求地址
     * @param clazz 返回类型
     * @return {@link T}
     * @author Fan
     * @since 2023/1/13 17:16
     */
    public static <T> T doGetWithObject(String url, Class<T> clazz) {
    
    
        return restTemplate.getForObject(url, clazz);
    }

    /**
     * 以 Post 方式请求第三方接口, postForEntity, 默认返回类型 String
     *
     * @param url    请求地址
     * @param object 请求参数
     * @return {@link String}
     * @author Fan
     * @since 2023/1/13 16:28
     */
    public static String doPostWithEntity(String url, Object object) {
    
    
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(url, object, String.class);

        return responseEntity.getBody();
    }

    /**
     * 以 Post 方式请求第三方接口, postForEntity, 指定返回类型
     *
     * @param url    请求地址
     * @param object 请求参数
     * @param clazz  返回类型
     * @return {@link T}
     * @author Fan
     * @since 2023/1/13 17:18
     */
    public static <T> T doPostWithEntity(String url, Object object, Class<T> clazz) {
    
    
        ResponseEntity<T> responseEntity = restTemplate.postForEntity(url, object, clazz);

        return responseEntity.getBody();
    }

    /**
     * 以 Post 方式请求第三方接口, postForObject, 返回值返回的是响应体, 省了再去 getBody(), 默认返回类型 String
     *
     * @param url    请求地址
     * @param object 请求参数
     * @return {@link String}
     * @author Fan
     * @since 2023/1/13 16:29
     */
    public static String doPostWithObject(String url, Object object) {
    
    
        return restTemplate.postForObject(url, object, String.class);
    }

    /**
     * 以 Post 方式请求第三方接口, postForObject, 返回值返回的是响应体, 省了再去 getBody(), 指定返回类型
     *
     * @param url    请求地址
     * @param object 请求参数
     * @param clazz  返回类型
     * @return {@link T}
     * @author Fan
     * @since 2023/1/13 17:19
     */
    public static <T> T doPostWithObject(String url, Object object, Class<T> clazz) {
    
    
        return restTemplate.postForObject(url, object, clazz);
    }
}

1.4 use

Test Controller

@RestController
public class RestTemplateTestController {
    
    

    @GetMapping("/test")
    public String test() {
    
    
        return RestTemplateUtil.doGetWithEntity("https://v1.hitokoto.cn");
    }
}

Start the project, here the port is changed to 8888, visithttp://localhost:8080/test

insert image description here

The one-word API is called here, and the call is successful

2. WebClient

Spring 3.0 introduced RestTemplate, but later introduced in the official source code, RestTemplate may be deprecated in future versions. Instead of RestTemplate, WebClient was introduced in Spring5 as a non-blocking Reactive Http client

2.1 Introducing dependencies

WebClient is in the spring-boot-starter-webflux package

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

2.2 use

WebClient does not need to be injected, it can be used directly

@RestController
public class WebClientSample {
    
    

    /**
     * WebClient.create() 方法
     *
     * @return {@link String}
     * @author Fan
     * @since 2023/1/31 14:01
     */
    @GetMapping("/create")
    public String create() {
    
    
        // 一个 Mono 对象包含 0 个或 1 个元素
        Mono<String> stringMono = WebClient
                // 创建 WebClient 实例
                .create()
                // 方法调用, 请求类型
                .method(HttpMethod.GET)
                // 请求 uri
                .uri("https://v1.hitokoto.cn")
                // 获取响应结果
                .retrieve()
                // 将结果转换为指定类型
                .bodyToMono(String.class);

        // 返回最终调用结果,block 方法是阻塞的
        return stringMono.block();
    }

    /**
     * WebClient.create(String baseUrl): 指定 baseUrl, 使用该客户端发送请求都是基于 baseUrl
     *
     * @author Fan
     * @since 2023/1/31 16:25
     */
    @GetMapping("/createWithBaseUrl")
    public void createWithBaseUrl() {
    
    
        // 一个 Flux 对象包含 1 个或多个元素
        Flux<String> stringFlux = WebClient.create("https://v1.hitokoto.cn")
                .get()
                // .uri("")
                .retrieve()
                .bodyToFlux(String.class);

        // 非阻塞式获取响应结果
        stringFlux.subscribe(this::handleResponse);
    }

    /**
     * 异步响应回调
     *
     * @param response 响应
     * @author Fan
     * @since 2023/1/31 14:25
     */
    private void handleResponse(String response) {
    
    
        LogUtil.info(response);
    }

    /**
     * WebClient.builder(): 返回一个 WebClient.Builder, 该对象可以做链式调用, 传递更多的参数 <br/>
     * <ul>
     *     <li>uriBuilderFactory: 自定义 UriBuilderFactory 灵活配置使用 Uri</li>
     *     <li>defaultHeader: 为 HTTP 请求设置 Headers 请求头</li>
     *     <li>defaultCookie: 为 HTTP 请求设置 Cookies</li>
     *     <li>defaultRequest: 自定义 HttpRequest</li>
     *     <li>filter: 为 HTTP 请求增加客户端过滤器</li>
     *     <li>exchangeStrategies: HTTP 读写信息自定义</li>
     *     <li>clientConnector: HTTP 客户端连接器设置</li>
     * </ul>
     *
     * @return {@link String}
     * @author Fan
     * @since 2023/1/31 14:02
     */
    @GetMapping("/build")
    public String build() {
    
    
        return WebClient.builder()
                .baseUrl("https://v1.hitokoto.cn")
                .defaultHeader("build", "build")
                .build()
                .get()
                // .uri("")
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }

    /**
     * exchange() 方法获取 HTTP 响应完整内容
     *
     * @author Fan
     * @since 2023/1/31 14:40
     */
    @GetMapping("/exchange")
    public String exchange() {
    
    
        return WebClient.create()
                .get()
                .uri("https://v1.hitokoto.cn")
                .exchangeToMono(clientResponse -> {
    
    
                    // 响应头
                    ClientResponse.Headers headers = clientResponse.headers();
                    // 响应状态
                    HttpStatus httpStatus = clientResponse.statusCode();
                    // 响应状态码
                    int rawStatusCode = clientResponse.rawStatusCode();
                    // 响应体
                    return clientResponse.bodyToMono(String.class);
                }).block();
    }

    /**
     * 数字占位符传参
     *
     * @author Fan
     * @since 2023/1/31 14:50
     */
    @GetMapping("/numParam")
    public String numParam() {
    
    
        return WebClient.create()
                .method(HttpMethod.POST)
                .uri("http://localhost:8080/user/{1}/{2}", ListUtil.list(false, 1, 2).toArray())
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }

    /**
     * 参数名传参
     *
     * @author Fan
     * @since 2023/1/31 14:53
     */
    @GetMapping("/nameParam")
    public String nameParam() {
    
    
        return WebClient.create()
                .method(HttpMethod.POST)
                .uri("http://localhost:8080/user/{id}/{name}", "id", "name")
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }

    /**
     * Map 传参
     *
     * @author Fan
     * @since 2023/1/31 14:54
     */
    @GetMapping("/mapParam")
    public String mapParam() {
    
    
        return WebClient.create()
                .method(HttpMethod.POST)
                .uri("http://localhost:8080/user/{id}/{name}",
                        MapUtil.ofEntries(false, MapUtil.entry("id", "id"), MapUtil.entry("name", "name")))
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }
}

Start the project, here the port is changed to 8888, visithttp://localhost:8888/build

insert image description here

Guess you like

Origin blog.csdn.net/ACE_U_005A/article/details/128820134