近期,Spring 6 的第一个 GA 版别发布了,其间带来了一个新的特性——HTTP Interface。这个新特性,能够让开发者将 HTTP 服务,界说成一个包括特定注解标记的办法的 Java 接口,然后经过对接口办法的调用,完结 HTTP 恳求。看起来很像运用 Feign 来完结长途服务调用,下面咱们参阅官方文档来完结一个 Demo。

完结一个 Demo

首要创立一个简略的 HTTP 服务,这一步能够创立一个简略的 Spring Boot 工程来完结。

先创立一个实体类

public class User implements Serializable {
    private int id;
    private String name;
    // 省略构造办法、Getter和Setter
    @Override
    public String toString() {
        return id + ":" + name;
    }
}

再写一个简略的 Controller:

@GetMapping("/users")
public List<User> list() {
    return IntStream.rangeClosed(1, 10)
            .mapToObj(i -> new User(i, "User" + i))
            .collect(Collectors.toList());
}

确保发动服务之后,能够从http://localhost:8080/users地址获取到一个包括十个用户信息的用户列表。

下面咱们新建一个 Spring Boot 工程。

Spring 6 的新特性:HTTP Interface

这里需要注意,Spring Boot 的版别至少需要是 3.0.0,这样它以来的 Spring Framework 版别才是 6.0 的版别,才能够包括 HTTP Interface 特性,另外,Spring Framework 6.0 和 Spring Boot 3.0 开端支撑的 Java 版别最低是 17,因而,需要选择至少是 17 的 Java 版别。

另外,需要依靠 Spring Web 和 Spring Reactive Web 依靠,原因下文中会说到。

创立好新的 Spring Boot 工程后,首要需要界说一个 HTTP Interface 接口。最简略的界说如下即可:

public interface UserApiService {
    @GetExchange("/users")
    List<User> getUsers();
}

然后,咱们能够写一个测验办法。

@Test
void getUsers() {
   WebClient client = WebClient.builder().baseUrl("http://localhost:8080/").build();
   HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(client)).build();
   UserApiService service = factory.createClient(UserApiService.class);
   List<User> users = service.getUsers();
   for (User user : users) {
      System.out.println(user);
   }
}

终究回打印获取到的是个用户信息:

1:User1
2:User2
...
9:User9
10:User10

以上是一个最简略的示例,下面咱们看看其间的一些细节。

GetExchange(HttpExchange)注解

上文比如中的 GetExchange 注解代表这个办法替代执行一个 HTTP Get 恳求,与此对应,Spring 还包括了其他类似的注解:

Spring 6 的新特性:HTTP Interface

这些注解界说在spring-web模块的org.springframework.web.service.annotation包下,除了 HttpExchange 之外,其他的几个都是 HttpExchange 的特殊方式,这一点与 Spring MVC 中的 RequestMapping/GetMapping 等注解十分类似。

以下是 HttpExchange 的源码:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
@Reflective(HttpExchangeReflectiveProcessor.class)
public @interface HttpExchange {
    @AliasFor("url")
    String value() default "";
    @AliasFor("value")
    String url() default "";
    String method() default "";
    String contentType() default "";
    String[] accept() default {};
}

在上面的比如中,咱们只指定了恳求的资源途径。

UserApiService 实例的创立

在上面比如中,咱们界说的 HTTP Interface 接口是 UserApiService,在测验办法中,咱们经过 HttpServiceProxyFactory 创立了 UserApiService 的实例,这是参阅了 Spring 的官方文档的写法。

你也能够将创立的进程写到一个 @Bean 办法中,然后能够将创立好的实例注入到其他的组件中。

咱们再界说 UserApiService 的时分,只是声明晰一个接口,那详细的恳求操作是怎么宣布的呢,咱们能够经过 DEBUG 模式看得出来,这里创立的 UserApiService 的实例,是一个署理目标:

Spring 6 的新特性:HTTP Interface

目前,Spring 还没有供给更方便的方式来创立这些署理目标,不过,之后的版别肯定会供给,如果你感兴趣的话,能够从 HttpServiceProxyFactory 的createClient办法的源码中看到一些与创立 AOP 署理类似的代码,因而,我推测 Spring 之后可能会添加类似的注解来方便地创立署理目标。

其他特性

除了上述比如中的简略运用之外,添加了 HttpExchange 的办法还支撑各种类型的参数,这一点也与 Spring MVC 的 Controller 办法类似,办法的返回值也能够是恣意自界说的实体类型(就像上面的比如相同),此外,还支撑自界说的反常处理。

为什么需要 Spring Reactive Web 的依靠

上文中创立工程的时分,引入了 Spring Reactive Web 的依靠,在创立署理的service目标的时分,运用了其间的 WebClient 类型。这是因为,HTTP Interface 目前只内置了 WebClient 的完成,它归于 Reactive Web 的领域。Spring 在会在后续版别中推出基于 RestTemplate 的完成。

总结

本文带你对 HTTP Interface 特性进行了简略的了解,我之后会深入研究这个特性,也会追踪后续版别中的改善并与你共享,欢迎点赞加重视。


本文正在参与「金石方案 . 瓜分6万现金大奖」