Spring Framework HTTP服务客户端详解

💡 原文中文,约6700字,阅读约需16分钟。
📝

内容提要

Spring Framework 7.0的HTTP服务客户端支持声明式接口、自动Bean注册和服务分组。通过@HttpExchange注解定义接口,用HttpServiceProxyFactory生成代理,适配RestClient、WebClient和RestTemplate。支持多种参数注解、自定义解析器、响应式返回类型和异常处理。服务分组功能可批量配置客户端,减少重复代码,被Spring Boot、Security和Cloud用于自动配置和负载均衡。

🔎

延伸解读

声明式接口与底层客户端解耦

HTTP服务客户端通过@HttpExchange注解定义接口,由HttpServiceProxyFactory生成代理,底层可适配RestClient、WebClient或RestTemplate。这种设计让业务代码不依赖具体HTTP客户端实现,便于切换或统一配置。服务端Controller也可实现同一接口,有助于前后端契约对齐,减少接口定义不一致的风险。

参数注解与自定义解析器

方法参数支持@PathVariable、@RequestParam、@RequestBody等常用注解,覆盖URL路径、查询参数、请求体等场景。对于复杂参数,可实现HttpServiceArgumentResolver自定义解析逻辑,例如将Search对象拆解为多个查询参数。这提高了接口定义的灵活性,但需注意自定义解析器需显式注册,且参数默认不允许为null,除非设置required=false。

服务分组减少重复配置

当接口数量较多时,服务分组机制允许将多个接口归为一组,共用一套客户端和代理工厂配置,并自动注册为Spring Bean。通过RestClientHttpServiceGroupConfigurer可批量修改分组配置,如添加默认请求头或拦截器。同一接口存在于多个分组时,需通过HttpServiceProxyRegistry按分组名获取客户端,避免类型注入冲突。

Q&A

Spring Framework 7.0 的 HTTP 服务客户端相比 6.0 新增了哪些核心能力?

Spring Framework 7.0 在原有声明式 HTTP 接口基础上,新增了自动 Bean 注册和服务分组管理,使得客户端配置更简洁,并支持批量配置和自动装配。

如何定义一个声明式 HTTP 接口并使用 @HttpExchange 注解?

定义一个 Java 接口,在方法上使用 @HttpExchange 或其派生注解(如 @GetExchange、@PostExchange)声明 HTTP 映射。例如:@GetExchange("/repos/{owner}/{repo}") Repository getRepository(@PathVariable String owner, @PathVariable String repo); 接口级别也可统一配置 URL 和 accept 等。

HttpServiceProxyFactory 如何适配 RestClient、WebClient 和 RestTemplate?

分别使用对应的适配器:RestClientAdapter.create(restClient)、WebClientAdapter.create(webClient)、RestTemplateAdapter.create(restTemplate),然后通过 HttpServiceProxyFactory.builderFor(adapter).build() 创建工厂,最后调用 factory.createClient(接口类) 获取代理客户端。

HTTP 服务客户端支持哪些方法参数注解?

支持 @RequestHeader、@PathVariable、@RequestAttribute、@RequestBody、@RequestParam、@RequestPart、@CookieValue 等,还支持 URI、UriBuilderFactory、HttpMethod 等特殊参数。参数默认不允许为 null,除非设置 required=false 或标记为可选。

如何自定义参数解析器来处理复杂参数对象?

实现 HttpServiceArgumentResolver 接口,在 resolve 方法中处理参数并添加到 HttpRequestValues.Builder。然后通过 HttpServiceProxyFactory.builderFor(adapter).customArgumentResolver(new MyResolver()).build() 注册。示例中自定义 Search 对象拆解为多个查询参数。

HTTP 服务客户端支持哪些返回值类型?

同步客户端(RestClient/RestTemplate)支持 void、HttpHeaders、实体 T、ResponseEntity(无响应体或完整响应)。响应式客户端(WebClient)额外支持 Mono、Flux 等。RestClientAdapter 还支持 InputStream 和 ResponseEntity<InputStream>。

如何处理 HTTP 服务客户端的异常?

默认 4xx/5xx 会抛出异常,可在底层客户端配置全局状态处理器,例如 RestClient 的 defaultStatusHandler 统一处理错误。也可通过 exchangeAdapterDecorator 包装适配器,实现如 404 不抛异常返回空实体的逻辑。

HTTP 服务分组是什么?如何使用?

服务分组允许将多个接口归为一组,共用一套客户端和代理工厂配置,并自动注册为 Spring Bean。可通过 @ImportHttpServices 注解声明分组,或编程式继承 AbstractHttpServiceRegistrar 注册。分组配置可通过 RestClientHttpServiceGroupConfigurer 批量修改。

同一接口在多个分组中时如何注入?

无法直接按类型注入,可通过注入 HttpServiceProxyRegistry,然后调用 registry.getClient("分组名", 接口类) 获取对应分组的客户端实例。

🏷️

标签

➡️

继续阅读