☰
Spring Cloud 抽公共 API:hm-api + Feign 扫不到 Bean 怎么修
2026/10/26 2:02:26 网站建设 项目流程

上一篇用DiscoveryClient+RestTemplate按服务名调商品。能跑,但每个调用方都要手写「拉实例 → 拼 URL → exchange」,DTO 还容易散在各服务里。

这篇只办两件事:

  1. 抽一个薄模块hm-api,专放跨服务契约

  2. 用OpenFeign替换手写 RestTemplate,并修掉「找不到 ItemClient Bean」

Gateway、Sentinel 不塞这篇。素材:黑马「抽取 Feign」+ 本机 hmall。

1. 为什么要从 RestTemplate 换成 Feign

DiscoveryClient + RestTemplateOpenFeign
写法自己拉实例、拼 URI、exchange接口 + 注解,像调本地方法
服务名字符串 + 手工选实例@FeignClient("item-service")
负载均衡自己 random / 后面再加@LoadBalanced配 LoadBalancer 即可
契约复用DTO/路径容易复制多份抽到hm-api一处维护

上篇是「看懂注册发现」;本篇是「声明式调用 + 契约模块化」。

2. 改造前后差在哪

改造前:商品服务里塞着 dto、FeignClient;购物车、订单直接依赖商品服务整坨。

改造后:

┌──────── hm-api ────────┐ │ client / dto / config │ └──────────▲─────────────┘ ┌───────────────────┼───────────────────┐ item-service cart-service order-service (实现商品) (依赖 api 调商品) (同上)
  • hm-api:接口 + 模型(普通 jar,不要做成可启动的 Boot 模块)

  • 业务服务:写实现;要远程调用的只依赖hm-api

3. IDEA 怎么建模块(和拆 item-service 同一套规矩)

新建模块→ Java/Maven,父工程选hmall,名称hm-api,JDK 与项目一致(如 11)。

父pom.xml必须有:

<module>hm-api</module>

推荐包:

com.hmall.api ├─ client # ItemClient、CartClient… ├─ dto # ItemDTO… └─ config # 可选:Feign 日志等

自检:父 modules 有没有登记;子模块有没有挂hmallparent。目录在父工程下但没挂 parent,只是文件夹——上篇 Maven 踩坑同样适用。

4. 调用方 pom 要带什么

业务服务(如 cart)依赖hm-api,还要能发 Feign:

<dependency> <groupId>com.hmall</groupId> <artifactId>hm-api</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>

groupId/ 版本以你父工程为准。Nacos discovery 上篇已配过,调用方继续连同一套server-addr。

5. 必踩坑:required a bean of type ItemClient

启动购物车时报类似:

Parameter 0 of constructor in ...CartServiceImpl required a bean of type 'com.hmall.api.client.ItemClient' that could not be found.

原因:@EnableFeignClients默认只扫启动类所在包及子包。启动类在com.hmall.cart,接口在com.hmall.api.client,扫不到就不生成代理 Bean。

修法一:扫包

@EnableFeignClients(basePackages = "com.hmall.api.client") @SpringBootApplication public class CartApplication { }

修法二:点名客户端

@EnableFeignClients(clients = { ItemClient.class }) @SpringBootApplication public class CartApplication { }

两个都行;客户端多时用扫包省事。

6. Feign 日志:怎么把请求响应打出来

OpenFeign不会默认把每次调用打到控制台。要日志,两件事一起做:

  1. Feign 所在包日志级别开到DEBUG

  2. 声明feign.Logger.Level的 Bean(注意是feign.Logger,不是 slf4j)

级别打什么
NONE不打(默认)
BASIC方法、URL、状态码、耗时
HEADERSBASIC + 头
FULL头 + Body,排障最全

本地用 FULL;生产慎用。

public class DefaultFeignConfig { @Bean public Logger.Level feignLoggerLevel() { return Logger.Level.FULL; } }

局部挂某一个 Client:

@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class) public interface ItemClient { }

全局默认:

@EnableFeignClients( basePackages = "com.hmall.api.client", defaultConfiguration = DefaultFeignConfig.class )

yaml:

logging: level: com.hmall.api.client: DEBUG

控制台若出现GET http://item-service/items?ids=...且是服务名不是写死 IP,说明走了注册中心 + LoadBalancer。

7. 自测顺序

  1. Nacos 已起,item-service已在服务列表

  2. cart 启动成功(不再报找不到 ItemClient)

  3. 调一个会远程查商品的接口,返回正常

  4. (可选)打开 FULL 日志,能看见 URL / 状态码 / Body

8. 一句话串讲

跨服务契约进hm-api;调用方依赖 api + OpenFeign + LoadBalancer。 找不到 ItemClient:@EnableFeignClients写basePackages或clients。 上篇手写发现是为了看懂;本篇 Feign 是为了少写样板、契约一处维护。要看明细就Logger.Level+ 包 DEBUG。

点记住
远程调用三件套openfeign + loadbalancer;@EnableFeignClients;写FeignClient
最佳实践提供方抽独立 api 模块:Client + DTO
扫不到 BeanbasePackages/clients
日志Level Bean + 包 DEBUG;局部configuration,全局defaultConfiguration

下篇预告

  • Gateway:统一入口

  • Sentinel:课上有再写

上一篇:Nacos 注册发现(含 No DataSource) 本篇:OpenFeign + hm-api 下篇:Gateway 统一入口(前端只打网关,不连 Nacos)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询