Spring Boot 3.0 新特性 - 声明式HTTP Client使用@HttpExchange

位置:首页>文章>详情   分类: 教程分享 > Java教程   阅读(4339)   2024-04-17 10:40:00

从Spring 6和Spring Boot 3开始,Spring framework支持将远程HTTP服务代理为带有HTTP交换注解方法的Java接口。类似的库,如OpenFeign和Retrofit,仍然可以使用,但HttpServiceProxyFactory添加了对Spring框架的原生支持。

1. 什么是声明式Http接口?

声明式HTTP接口是一种Java接口,它有助于减少模板代码,生成实现该接口的代理,并在框架级别执行交换。

例如,如果我们想在URL https://server-address.com/api/resource/id上使用API,那么我们需要创建并配置RestTemplate或WebClient bean,并使用其交换方法来调用API、解析响应和处理错误。

大多数情况下,创建和配置bean以及调用远程api的代码非常相似,因此可以被框架抽象,因此我们不需要在每个应用程序中反复编写此代码。我们可以简单地使用接口上的注释来表达远程API的详细信息,并让框架在后台创建实现。

例如,如果我们想使用HTTP GET /users API,那么我们可以简单地编写:

public interface UserClient {
  @GetExchange("/users")
  Flux<User> getAll();
}

Spring会在运行时提供接口和exchange实现,我们只需要调用getAll()方法。

@Autowired
UserClient userClient;
userClient.getAll().subscribe(
    data -> log.info("User: {}", data)
);

2. Maven


声明式HTTP接口功能是spring-web依赖的一部分,当我们引入spring-boot-starter-web或spring-boot-starter-webflux时,它就会被传递引入。如果我们想添加响应式支持,那么就包括后面的依赖。
 

<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>

3.创建HTTP服务接口

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

3.1. 交流的方法

我们可以使用以下注解将方法标记为HTTP服务端点:
 

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

3.2. 方法参数

exchange方法在方法签名中支持下列方法参数:

  • URI:设置请求的URL。
  • @PathVariable:将请求URL中的值替换为占位符。
  • @RequestBody:提供请求的主体。
  • @RequestParam:添加请求参数。当“content-type”设置为“application/x-www-form-urlencoded”时,请求参数会在请求体中编码。否则,它们将作为URL查询参数添加。
  • @ requesttheader:添加请求头的名称和值。
  • @RequestPart:可用于添加请求部分(表单字段,资源或HttpEntity等)。
  • @CookieValue:向请求中添加cookie。

示例代码:

@PutExchange
void update(@PathVariable Long id, @RequestBody User user);

3.3. 返回值

HTTP exchange方法可以返回如下值:

  • 阻塞或反应性(Mono/Flux)。
  • 只有特定的响应信息,如状态码和/或响应头。
  • Void,表示该方法仅被视为execute方法;

对于阻塞交换方法,我们通常应该返回ResponseEntity,而对于响应式方法,我们可以返回Mono/Flux类型。

//阻塞性
@GetExchange("/{id}")
User getById(...);

//Reactive
@GetExchange("/{id}")
Mono<User> getById(...);


 

4 构建HttpServiceProxyFactory

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

import com.fasterxml.jackson.databind.ObjectMapper;
import com.leftso.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);
  }
}


注意,我们已经在WebClient bean中设置了远程API的基础URL,因此我们只需要在交换方法中使用相对路径。
 

5. HTTP业务接口示例


下面是与https://jsonplaceholder.typicode.com/users/端点交互并执行各种操作的HTTP接口示例。

import com.leftso.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);
}

注意,我们创建了一个User类型的记录来保存用户信息。

public record User(Long id, String name, String username, String email) {}

现在我们可以将UserClient bean注入到应用程序类中,并调用方法以获取API响应。

@Autowired
UserClient userClient;
//获取所有用户
userClient.getAll().subscribe(
    data -> log.info("User: {}", data)
);
//通过id获取用户
userClient.getById(1L).subscribe(
    data -> log.info("User: {}", data)
);
//创建一个新用户
userClient.save(new User(null, "Lokesh", "lokesh", "admin@email.com"))
    .subscribe(
        data -> log.info("User: {}", data)
    );
//通过id删除用户
userClient.delete(1L).subscribe(
    data -> log.info("User: {}", data)
);

6. 总结

在这个Spring(Spring Boot 3.0)教程中,我们通过示例学习了如何创建和使用声明式HTTP客户端接口。我们学习了如何在接口中创建交换方法,然后使用Spring框架创建的代理实现调用它们。我们还学习了如何使用HttpServiceProxyFactory和WebClient bean创建接口代理。
 

地址:https://www.leftso.com/article/1117.html

相关阅读

从Spring 6和Spring Boot 3开始,Spring framework支持将远程HTTP服务代理为带有HTTP交换注解方法的Java接口。类似的库,如OpenFeign和Retro...
从Spring 6和Spring Boot 3开始,与OpenFeign和Retrofit等其他声明式客户端类似,Spring框架支持以Java接口的形式创建RSocket服务,并为RSocke...
从Spring 6和Spring Boot 3开始,Spring框架支持“HTTP API的问题详细信息”规范RFC 7807。本Spring Boot 教程将详细指导您完成这一新增强。1.问题...
Spring Boot 2.0 有哪些新特性_Spring Boot 2.0新功能,在本文中,我们将探讨为Spring Boot 2.0计划的一些更改和功能。我们还会描述这些变化如何帮助我们提高...
Spring Boot 2.0 Redis整合,通过spring boot 2.0整合Redis作为spring缓存框架的实现。
spring boot 2.0 security 5.0 整合,实现自定义表单登录。spring boot 2.0框架使用。
Spring Boot 2.0,Spring框架的Spring Boot 中的Spring Boot Actuator变化讲解。并且了解如何在Spring Boot 2.0中使用Actuator...
Spring Boot 1.x升级到Spring Boot 2.0迁移指南
Spring Boot 2.0 绑定properties属性资源文件 Spring Boot 2.0 读取properties配置文件值 Spring Boot 2.0获取properties配...
Spring Boot 2.1 新特性,已升级Spring 版本为5.1,支持servlet 4.0,支持Tomcat 9.0等等