替换OpenFeign,SpringBoot 3.0 新版本自带的 HTTP 客户端工具来了!

点击关注公众号,实用技术文章及时了解替换OpenFeign,SpringBoot 3.0 新版本自带的 HTTP 客户端工具来了!


我们在日常开发中,经常会需要远程调用其他服务提供的接口,比较常用的 HTTP 远程代理框架有OpenFeign、Retrofit以及一些第三方封装工具类,例如Hutool提供的HttpUtil。

11月24日,Spring Boot 3正式发布,Spring官方已经自身支持使用声明式服务调用的方式来调用远程接口。

替换OpenFeign,SpringBoot 3.0 新版本自带的 HTTP 客户端工具来了!

虽然类似的远程调用框架如OpenFeign和Retrofit仍然可以使用,但HttpServiceProxyFactory增加了对 Spring 框架的原生支持。如果Spring本身可以做到远程调用的话,这些大量的第三方库应该很快会被原生方法取代,我们今天来了解一下这个新特征。

声明式 Http 接口

声明性 HTTP 接口可以让你像定义Java接口那样定义HTTP服务,用法和你平时写Controller中方法完全一致。

引入

声明性 HTTP 接口功能是spring-web依赖项的一部分,使用前必须引入如下依赖包:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- For reactive support -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
创建 HTTP 服务接口

在 Spring 中,HTTP 服务接口是一个带有@HttpExchange方法的 Java 接口。注释方法被视为 HTTP 端点,细节通过注释属性和输入方法参数类型静态定义。

支持的注解类型

  • @HttpExchange:是用于指定 HTTP 端点的通用注释。在接口级别使用时,它适用于所有方法。
  • @GetExchange:为 HTTP GET请求指定@HttpExchange
  • @PostExchange:为 HTTP POST请求指定@HttpExchange
  • @PutExchange:为 HTTP PUT请求指定@HttpExchange
  • @DeleteExchange:为 HTTP DELETE请求指定@HttpExchange
  • @PatchExchange:为 HTTP PATCH请求指定@HttpExchange

方法参数

替换OpenFeign,SpringBoot 3.0 新版本自带的 HTTP 客户端工具来了!

返回值

声明性 HTTP 接口支持以下返回值:

替换OpenFeign,SpringBoot 3.0 新版本自带的 HTTP 客户端工具来了!

使用示例

@PutExchange
void update(@PathVariable Long id, @RequestBody User user);
完整使用案例

我们以一个简单的用户信息请求为例

0、构建HttpServiceProxyFactory

HttpServiceProxyFactory是一个从 HTTP 服务接口创建客户端代理的工厂类。使用HttpServiceProxyFactory.builder(client).build()方法来获取代理 bean 的实例。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.howtodoinjava.app.web.UserClient;
import lombok.SneakyThrows;
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 WebConfig {
  @Bean
  WebClient webClient(ObjectMapper objectMapper) {
    return WebClient.builder()
        .baseUrl("https://jsonplaceholder.typicode.com/")
        .build();
  }
  @SneakyThrows
  @Bean
  UserClient postClient(WebClient webClient) {
    HttpServiceProxyFactory httpServiceProxyFactory =
        HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient))
            .build();
    return httpServiceProxyFactory.createClient(UserClient.class);
  }
}

1、定义一个简单的用户信息实体类:

public class User {

    private int id;

    private String username;

    private String password;
  
   // 省略

}

2、请求接口:

import com.howtodoinjava.app.model.User;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.service.annotation.DeleteExchange;
import org.springframework.web.service.annotation.GetExchange;
import org.springframework.web.service.annotation.HttpExchange;
import org.springframework.web.service.annotation.PostExchange;
import org.springframework.web.service.annotation.PutExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@HttpExchange(url = "/users", accept = "application/json", contentType = "application/json")
public interface UserClient {
  @GetExchange("/")
  Flux<User> getAll();
  @GetExchange("/{id}")
  Mono<User> getById(@PathVariable("id") Long id);
  @PostExchange("/")
  Mono<ResponseEntity<Void>> save(@RequestBody User user);
  @PutExchange("/{id}")
  Mono<ResponseEntity<Void>> update(@PathVariable Long id, @RequestBody User user);
  @DeleteExchange("/{id}")
  Mono<ResponseEntity<Void>> delete(@PathVariable Long id);
}

3、将UserClient bean 注入应用程序类并调用方法来获取 API 响应:

@Autowired
UserClient userClient;
//Get All Users
userClient.getAll().subscribe(
    data -> log.info("User: {}", data)
);
//Get User By Id
userClient.getById(1L).subscribe(
    data -> log.info("User: {}", data)
);
//Create a New User
userClient.save(new User(null"Lokesh""lokesh""admin@email.com"))
    .subscribe(
        data -> log.info("User: {}", data)
    );
//Delete User By Id
userClient.delete(1L).subscribe(
    data -> log.info("User: {}", data)
);

完工,不需要定义方法实现就能进行远程HTTP调用,非常方便!

扩展

1、Spring Boot3 新特征一览:

  • https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes

2、文章相关代码:

  • https://github.com/lokeshgupta1981/Spring-Boot3-Demos/tree/main/declarative-http-client-example

3、Spring官方文档介绍:

  • https://docs.spring.io/spring-framework/docs/6.0.0-RC1/reference/html/integration.html#rest-http-interface

推荐

Java面试题宝典

技术内卷群,一起来学习!!

替换OpenFeign,SpringBoot 3.0 新版本自带的 HTTP 客户端工具来了!

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。“在看”支持我们吧!

原文始发于微信公众号(Java知音):替换OpenFeign,SpringBoot 3.0 新版本自带的 HTTP 客户端工具来了!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/65723.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!