OpenFeign:声明式 HTTP 调用与参数传递

RestTemplate 每次调用都要拼 URL、选方法、处理响应,代码重复且容易出错。OpenFeign 的思路是"把远程调用声明成一个 Java 接口":接口方法上的注解描述 HTTP 请求长什么样,调用接口方法就像调用本地方法。Spring Cloud 对 OpenFeign 做了封装,能自动接入注册中心与负载均衡,是微服务互调的主流方式。本章基于第 01 章版本锚点(Spring Cloud 2025.0.x),以 order-service 调用 user-service 为例。

引入依赖并开启 Feign

order-service 的 pom 中加入 openfeign starter(版本由 spring-cloud-dependencies BOM 管理),在启动类或配置类上加 @EnableFeignClients:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
@SpringBootApplication
@EnableFeignClients   // 扫描 @FeignClient 接口并生成实现
public class OrderApplication { }

定义一个远程调用接口

用 @FeignClient 声明目标服务,name 是注册中心里的服务名(第 03 章已注册的 user-service),接口方法按 HTTP 语义描述请求:

@FeignClient(name = "user-service")
public interface UserClient {
    @GetMapping("/api/user/{id}")
    UserDto getUser(@PathVariable("id") Long id);
}

调用方注入 UserClient 后直接调方法即可。运行时 OpenFeign 会生成该接口的代理:方法上的 Spring MVC 注解(@GetMapping、@PostMapping 等)被翻译成 HTTP 请求,服务名交给负载均衡器解析成真实实例地址(第 07 章)。

参数传递的四种形态

OpenFeign 参数注解沿用 Spring MVC 注解,规则与 Controller 一致:

@FeignClient(name = "user-service")
public interface UserClient {
    // 1. 路径参数:注解值必须写全,路径里的 {id} 与参数注解一一对应
    @GetMapping("/api/user/{id}")
    UserDto getUser(@PathVariable("id") Long id);

    // 2. 查询参数:多个参数会拼成 ?name=xxx&page=1
    @GetMapping("/api/user/search")
    List<UserDto> search(@RequestParam("name") String name,
                         @RequestParam("page") int page);

    // 3. 请求体:只能有一个无注解的复杂对象,默认 Jackson 序列化为 JSON
    @PostMapping("/api/user")
    UserDto create(@RequestBody UserCreateCmd cmd);

    // 4. 请求头:透传或固定 header
    @GetMapping("/api/user/header")
    String echoHeader(@RequestHeader("X-Token") String token);
}

易错点:一是 @PathVariable 注解里要写参数名,否则需在编译期加 -parameters 参数;二是方法名随意、注解才决定请求,不要靠方法名猜行为;三是 GET 请求传复杂对象时,Feign 默认不会把对象序列化进 query,需要时改用 Map 拼参数或自定义编码器。

服务端如何接收

被调方 user-service 的 Controller 就是普通写法:@PathVariable、@RequestParam、@RequestBody 一一对应即可,调用方与服务端参数名不一致是常见的 400 错误来源,调试时先核对两端注解。

按客户端定制配置

OpenFeign 支持按服务名或全局定制超时、日志级别等,例如只对 user-service 调大日志:

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            logger-level: basic
          user-service:
            logger-level: full

日志级别有 NONE、BASIC、HEADERS、FULL 四档,FULL 能看到请求头与响应体,排障利器;也可以为单个 FeignClient 用 configuration 属性指定独立配置类,细节以官方文档为准。

小结

OpenFeign 把远程调用收敛成"接口 + 注解",代码直观、可单测、可复用;参数传递规则与 Spring MVC 对齐,掌握路径/查询/请求体/请求头四种形态即可覆盖日常开发。调用能"发出去"之后,真正的工程难点在于发出去的请求超时了、失败了怎么处理,这正是下一章的主题。

笔记加载中…