Spring Cloud 组件 —— feign
feign 作为一个声明式的 Http Client 开源项目。在微服务领域,相比于传统的 apache httpclient 与在 spring 中较为活跃的 RestTemplate 更面向服务化,更易于使用。底层封装了 Jersey 与 CXF 分别用于 REsT 与 SOAP 的服务(对应有 JAX-RS 与 JAX-WS API),当然也可以配置换成其它类似的实现,比如 OkHttp 、Ribbon 或者 Apache HC 等。
feign 基本用法及注解的使用看官方文档。下面介绍下 Spring Cloud 中的封装及实现细节(Spring Cloud 文档):
一、 基本用法
现有服务提供方:需要调用它的 createUser 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | @RestController @RequestMapping ( "/users" ) public class UserController { @Autowired private UserService userService; @RequestMapping (value = "/current" , method = RequestMethod.GET) public Principal getUser(Principal principal) { return principal; } @PreAuthorize ( "#oauth2.hasScope('server')" ) @RequestMapping (method = RequestMethod.POST) public void createUser( @Valid @RequestBody User user) { userService.create(user); } } |
使用 feign 构建消费服务方,遵循以下步骤:
引入 maven 依赖
1 2 3 4 | <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> |
1. 启用:使用 @EnableFeignClients 注解启动 feign 模块基础功能(扫描 feign client包,使用默认或指定的相关配置等等)
1 2 3 4 5 6 7 8 9 | @SpringBootApplication @EnableFeignClients public class Application { public static void main(String[] args) { SpringApplication.run(Application. class , args); } } |
2. 声明:使用 @FeignClient("app-name") 创建声明式的 HC:很简单配置下 service 名称/url 与 发出请求的路径就好了。
1 2 3 4 5 6 7 | @FeignClient (name = "auth-service" ) public interface AuthServiceClient { @RequestMapping (method = RequestMethod.POST, value = "/users" , consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) void createUser(User user); } |
3. 调用:上面的代码,相对于服务提供方,它是客户端服务消费方。相对于服务消费方自身,它上升到一个 service,因此我们可以在 service 层或 controller 层调用它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | @Service public class AccountServiceImpl implements AccountService { private final Logger log = LoggerFactory.getLogger(getClass()); @Autowired private AuthServiceClient authClient; @Autowired private AccountRepository repository; /** * {@inheritDoc} */ @Override public Account create(User user) { Account existing = repository.findByName(user.getUsername()); Assert.isNull(existing, "account already exists: " + user.getUsername()); // 调用feign HC服务 authClient.createUser(user); Saving saving = new Saving(); saving.setAmount( new BigDecimal( 0 )); saving.setCurrency(Currency.getDefault()); saving.setInterest( new BigDecimal( 0 )); saving.setDeposit( false ); saving.setCapitalization( false ); Account account = new Account(); account.setName(user.getUsername()); account.setLastSeen( new Date()); account.setSaving(saving); repository.save(account); log.info( "new account has been created: " + account.getName()); return account; } ... |
二、feign 的相关配置(比如日志、hytrix 等)
配置方式有 3种:
1. 使用 JavaConfig 方式
配置类(这里建议不要加 @Configuration 注解,否则将变成全局配置)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public class FileConf { private final ObjectFactory<HttpMessageConverters> messageConverters; @Autowired public FileConf(ObjectFactory<HttpMessageConverters> messageConverters) { this .messageConverters = messageConverters; } @Bean public Encoder feignFormEncoder() { return new SpringFormEncoder( new SpringEncoder(messageConverters)); } } |
调用端
1 2 3 4 5 6 7 8 9 10 11 12 | @FeignClient (value = "service-thirdparty" , configuration = FileConf. class ) @RequestMapping (value = "/storage" ) public interface StorageClient { /** * 上传图片 */ @RequestMapping ( value = "/imageUpload" , method = RequestMethod.POST, consumes = MULTIPART_FORM_DATA_VALUE) BusinessResult uploadImage( @RequestParam (value = "bucket" ) String bucket, @RequestPart (value = "file" , required = false ) MultipartFile file); |
2. 使用 application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | # To disable Hystrix in Feign feign: client: config: default : connectTimeout: 5000 readTimeout: 5000 loggerLevel: basic hystrix: enabled: false # To set thread isolation to SEMAPHORE hystrix: command: default : execution: isolation: strategy: SEMAPHORE logging.level.project.user.UserClient: DEBUG |
注意事项:
① 如果 @Configuration的 JavaConfig 与 properties 配置同时存在,那么后者会覆盖前者。通过设定 feign.client.default-to-properties
to false
. 改变优先权。
② 只有开启 DEBUG级别的日志, feign 的log功能才会生效。
③ 如果 classpath 引入了 hytrix(如下),并且配置启用 hytrix(比如 feign.hystrix.enabled=true),那么默认会启用 circuit breaker 。
1 2 3 4 | <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> |
在 Spring Cloud Dalston 及之后的版本中,circuit breaker 是可选操作。需要使用 @EnableCircuitBreaker 手动开启。
1 2 3 4 | @SpringBootApplication @EnableFeignClients @EnableCircuitBreaker public class Application { |
扩展:使用断路器功能
声明:
1 2 3 4 5 6 7 | @FeignClient (name = "statistics-service" , fallback = StatisticsServiceClientFallback. class ) public interface StatisticsServiceClient { @RequestMapping (method = RequestMethod.PUT, value = "/statistics/{accountName}" , consumes = MediaType.APPLICATION_JSON_UTF8_VALUE) void updateStatistics( @PathVariable ( "accountName" ) String accountName, Account account); } |
定义 hytrix:
1 2 3 4 5 6 7 8 | @Component public class StatisticsServiceClientFallback implements StatisticsServiceClient { private static final Logger LOGGER = LoggerFactory.getLogger(StatisticsServiceClientFallback. class ); @Override public void updateStatistics(String accountName, Account account) { LOGGER.error( "Error during update statistics for account: {}" , accountName); } } |
233
参考资料
https://github.com/sqshq/PiggyMetrics (完整示例)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix