Spring Cloud OpenFeign 提供了一种声明式、模板化的HTTP客户端,可以通过简单的接口描述远程调用,而不必手动编写低级的 HTTP 客户端代码。FeignClient用法参考:FeignClient用法-笔记-CSDN博客。这里梳理Spring Cloud OpenFeign 常用注解。
1. @FeignClient
功能:声明一个Feign客户端,用于访问远程服务。
适用场景:定义需要调用的其他微服务的接口。
注意事项:
name
或value
属性指定服务名(在服务注册中心注册的名称)。- 可以配置URL直接指定地址(用于测试或非注册中心场景)。
- 支持配置降级处理(通过
fallback
或fallbackFactory
)。
示例:
@FeignClient(name = "user-service", url = "http://localhost:8080", fallback = UserClientFallback.class)
public interface UserClient {
@GetMapping("/users/{id}")
User getUserById(@PathVariable("id") Long id);
}
// 降级实现
@Component
public class UserClientFallback implements UserClient {
@Override
public User getUserById(Long id) {
return new User(0L, "默认用户");
}
}
2. @RequestMapping
及变种
@RequestMapping
及变种 (@GetMapping
, @PostMapping
等):
功能:指定Feign客户端方法对应的HTTP方法和路径。
适用场景:定义远程调用的具体端点。
注意事项:
- 与Spring MVC中的用法一致,但用于Feign客户端接口。
- 路径中可以使用占位符(配合
@PathVariable
使用)。
示例:
@FeignClient(name = "order-service")
public interface OrderClient {
@PostMapping("/orders")
Order createOrder(@RequestBody Order order);
@GetMapping("/orders/{orderId}")
Order getOrder(@PathVariable("orderId") String orderId);
}
3. @PathVariable
功能:将方法参数绑定到URI模板变量。
适用场景:当URL路径中包含动态变量时(如RESTful风格)。
注意事项:
- 必须指定
value
或name
属性来匹配URI模板中的变量名(与 MVC 不同,在Feign中必须显式指定,不能省略)。 - 不支持 Spring MVC 的
@PathVariable(required = false)
- 路径变量不能为空
示例:
@FeignClient(name = "product-service")
public interface ProductClient {
@GetMapping("/products/{productId}")
Product getProduct(@PathVariable("productId") Long id); // 注意:这里必须指定"productId"
}
4. @RequestHeader
功能:将方法参数绑定到HTTP请求头。
适用场景:需要传递自定义HTTP头信息(如认证token)。
- 传递认证令牌(Authorization)
- 设置内容协商头(Accept)
- 自定义业务标识头
注意事项:
- 可以传递单个值,也可以传递
Map
来设置多个请求头。 - 支持占位符表达式
- 不会被 Spring MVC 的
@RequestHeader
解析 - 如果请求头的值是动态的,必须用
@RequestHeader
注解。
示例:
@FeignClient(name = "auth-service")
public interface AuthClient {
@GetMapping("/userinfo")
UserInfo getUserInfo(@RequestHeader("Authorization") String token);
// 传递多个请求头
@PostMapping("/update")
void update(@RequestHeader Map<String, String> headers, @RequestBody UserInfo userInfo);
}
5. @RequestParam
功能:将方法参数绑定到HTTP请求参数(URL查询参数)。
适用场景:
- 传递单个或少量查询参数。
- 非结构化参数传递
- 数组/集合类型参数
注意事项:
- 数组参数格式:
?ids=1,2,3
或?ids=1&ids=2
- 如果参数是可选,需要设置
required=false
(默认是true
)。 - 当参数较多时,建议使用
@SpringQueryMap
代替。
示例:
@FeignClient(name = "search-service")
public interface SearchClient {
@GetMapping("/search")
List<Product> searchProducts(@RequestParam("kw") String keyword,
@RequestParam(value = "page", required = false, defaultValue = "0") int page);
// 数组参数
@DeleteMapping("/items")
void deleteItems(@RequestParam("ids") List<Long> ids);
}
6. @SpringQueryMap
功能:将POJO对象转换为URL查询参数。当我们需要将一个对象作为查询参数传递给另一个服务时,使用这个注解可以避免手动拼接URL查询字符串。
适用场景:
- 在Feign客户端中,需要传递多个查询参数,而这些参数被封装在一个对象中。
- 传递复杂或多条件的查询参数(避免在方法中写多个
@RequestParam
)。
注意事项:
- 支持嵌套对象的转换(通过点号
.
连接属性,如user.address.city
)。 - 只能用于Feign客户端。
- 适用于GET请求,因为GET请求通常使用查询参数传递数据。
- GET 请求参数长度限制(约 2048 字符)
示例:
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/users/search")
List<User> searchUsers(@SpringQueryMap UserSearchCriteria criteria);
}
// 查询条件POJO
public class UserSearchCriteria {
private String name;
private Integer age;
private Address address; // 嵌套对象
// getters and setters
}
public class Address {
private String city;
private String street;
// getters and setters
}
//当我们调用userClient.searchUsers(new UserQuery("张三", 25,new Address("beijing","xierqi")))时,
//Feign会生成一个URL:/users?name=张三&age=25&address.city=beijing&address.street=xierqi。
补充说明:
在Spring MVC中,如果我们想在Controller的方法中接收多个查询参数,可以直接使用一个POJO对象作为参数,而不需要任何注解,Spring MVC会自动将查询参数绑定到对象中(但要求该对象有默认构造函数,并且属性名与查询参数名匹配)。例如:
@Controller
public class UserController {
@GetMapping("/users/search")
List<User> searchUsers(UserSearchCriteria criteria){
//......
}
}
但是,在Feign客户端中,我们不能直接这样做,因为Feign默认不会将对象转换为查询参数,所以需要使用@SpringQueryMap
注解。
总结:
注解 | 功能 | 适用场景 | 注意事项 |
---|---|---|---|
@FeignClient |
声明Feign客户端 | 定义远程服务调用接口 | 配置服务名、URL、降级等 |
@RequestMapping |
指定HTTP方法和路径 | 定义远程调用的端点 | 支持各种HTTP方法注解变体 |
@PathVariable |
绑定路径变量 | RESTful风格的URL路径参数 | 必须显式指定变量名 |
@RequestHeader |
绑定请求头 | 传递自定义头信息(如认证token) | 可传递单个头或多个头(Map) |
@RequestParam |
绑定查询参数 | 传递少量查询条件 | 可选参数需设置required=false |
@SpringQueryMap |
POJO转查询参数 | 传递复杂或多条件查询 | 支持嵌套对象,只能用于Feign |
使用这些注解,可以方便地定义Feign客户端,实现微服务之间的优雅调用。常见用法总结:
- 服务间调用:首选
@FeignClient
+ Spring Cloud 服务发现 - GET 参数:
- 简单参数 →
@RequestParam
- 复杂参数 →
@SpringQueryMap
- 简单参数 →
- 路径参数:必须显式命名
@PathVariable("id")
- 请求头:动态头用
@RequestHeader
- 特殊格式:
- 表单 → 自定义
Encoder
- 文件 →
@RequestPart
(需额外配置)
- 表单 → 自定义
- 错误处理:
- 熔断降级 →
fallback
/fallbackFactory
- 错误解码 → 实现
ErrorDecoder
- 熔断降级 →
一个完整示例:
// 完整示例
@FeignClient(
name = "user-service",
fallbackFactory = UserClientFallbackFactory.class
)
public interface UserClient {
@GetMapping("/users/{userId}")
User getUser(
@PathVariable("userId") String id,
@RequestHeader("X-Trace-Id") String traceId
);
@PostMapping("/users/search")
List<User> searchUsers(
@SpringQueryMap UserQuery query,
@RequestHeader Map<String, String> headers
);
}
@Component
public class UserClientFallbackFactory implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable cause) {
return new UserClient() {
@Override
public User getUser(String id, String traceId) {
return new User("fallback-user");
}
// ...其他方法降级实现
};
}
}