微服务实战SpringCloud之Spring Cloud Feign
简介
在项目中我们有时候需要调用第三方的API,微服务架构中这种情况则更是无法避免——各个微服务之间通信。比如一般的项目中,有时候我们会使用 HTTP Client 发送 HTTP 请求来进行调用,而在微服务架构,Spring Cloud 全家桶中,Spring Cloud Feign 则是更常见的选择。那么,我如何只使用 Spring Cloud Feign 而不引入整个 Spring Cloud 呢?
什么是Feign?
Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。
而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon和Hystrix,可以让我们不再需要显式地使用这两个组件。
总起来说,Feign具有如下特性:
- 可插拔的注解支持,包括Feign注解和JAX-RS注解;
- 支持可插拔的HTTP编码器和解码器;
- 支持Hystrix和它的Fallback;
- 支持Ribbon的负载均衡;
- 支持HTTP请求和响应的压缩。
这看起来有点像我们springmvc模式的Controller层的RequestMapping映射。这种模式是我们非常喜欢的。Feign是用@FeignClient来映射服务的。
首先找一个AIP
免费的API特别多,github上也有免费API地址汇总的repo,但这些都太正式了。有趣的事物总是会相互吸引的,无意间我发现了这么一个网站,“渣男:说话的艺术”(lovelive.tools) ,每次请求都可以获取一句甜言蜜语(渣男语录),特别良心的是,作者提供了API列表,给作者点赞!
如何调用第三方服务?
首先,我们先快速构建一个 Spring Boot 的 web 项目,这里我就省略了。然后在pom中添加feign的相关依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> <version>2.1.3.RELEASE</version> </dependency>
然后,在启动类添加响应的注解 @EnableFeignClients:
1 2 3 4 5 6 7 | @SpringBootApplication @EnableFeignClients public class SpringbootMiddlewareFeignApplication { public static void main(String[] args) { SpringApplication.run(SpringbootMiddlewareFeignApplication. class , args); } } |
接着,我们便可以配置我们的 Client 了,我们先创建一个接口类,比如叫BadGuyFeignClient ,并声明为 FeignClient:
@FeignClient public interface BadGuyFeignClient { }
@FeignClient有以下几个较常用属性:
属性名 | 默认值 | 作用 | 备注 |
---|---|---|---|
value | 空字符串 | 调用服务名称,和name属性相同,如果项目使用了 Ribbon,name属性会作为微服务的名称,用于服务发现; | |
serviceId | 空字符串 | 服务id,作用和name属性相同 | 已过期 |
name | 空字符串 | 调用服务名称,和value属性相同,如果项目使用了 Ribbon,name属性会作为微服务的名称,用于服务发现; | |
url | 空字符串 | url一般用于调试,可以手动指定@FeignClient调用的地址 | |
decode404 | false | 配置响应状态码为404时是否应该抛出FeignExceptions | |
configuration | {} | Feign配置类,可以自定义 Feign的 Encoder、Decoder、LogLevel、Contract; | 参考FeignClientsConfiguration |
fallback | void.class | 定义容错的处理类,当调用远程接口失败或超时时,会调用对应接口的容错逻辑,fallback指定的类必须实现@FeignClient标记的接口 | 底层依赖hystrix,启动类要加上@EnableHystrix |
fallbackFactory | void.class | 工厂类,用于生成fallback类示例,通过这个属性我们可以实现每个接口通用的容错逻辑,减少重复的代码 | |
path | 空字符串 | 自动给所有方法的requestMapping前加上前缀,类似与controller类上的requestMapping |
然后,我们便可以配置对应的属性,这里我们只是用来实现类似于 HTTP Client 的功能,所以只是简单配置了url和path这些属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @FeignClient (name = "badGuy" , url = "${bab.guy.url}" , path = "api" ) public interface BadGuyFeignClient { /** * 随机获取一句甜言蜜语 * * @return */ @GetMapping ( "SweetNothings" ) String getSweetNothings(); /** * 获取 count 条甜言蜜语 * * @param count 获取甜言蜜语条数 * @return Json 格式的结果 */ @GetMapping ( "SweetNothings/{count}/Serialization/Json" ) ReturnResult<List<String>> getSweetNothingsJsonByCount( @PathVariable ( "count" ) Integer count); } |
声明为FeignClient之后,我们便可以在代码中使用@Resource或者@Autowire进行注入使用了:
提示 org.apache.http.impl.client.HttpClientBuilder 这个类找不到 问题的解决
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 | java.lang.IllegalStateException: Error processing condition on org.springframework.cloud.commons.httpclient.HttpClientConfiguration$ApacheHttpClientConfiguration.apacheHttpClientBuilder at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java: 60 ) ~[spring-boot-autoconfigure- 2.3 . 3 .RELEASE.jar: 2.3 . 3 .RELEASE] ...... Caused by: java.lang.IllegalStateException: @ConditionalOnMissingBean did not specify a bean using type, name or annotation and the attempt to deduce the bean's type failed at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.validate(OnBeanCondition.java: 487 ) ~[spring-boot-autoconfigure- 2.3 . 3 .RELEASE.jar: 2.3 . 3 .RELEASE] ...... ... 18 common frames omitted Caused by: org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanTypeDeductionException: Failed to deduce bean type for org.springframework.cloud.commons.httpclient.HttpClientConfiguration$ApacheHttpClientConfiguration.apacheHttpClientBuilder ...... ... 20 common frames omitted Caused by: java.lang.ClassNotFoundException: org.apache.http.impl.client.HttpClientBuilder ...... ... 22 common frames omitted 2021 - 03 - 15 07 : 34 : 52.548 WARN 11915 --- [ main] o.s.boot.SpringApplication : Unable to close ApplicationContext java.lang.IllegalStateException: Failed to introspect Class [org.springframework.cloud.commons.httpclient.HttpClientConfiguration$ApacheHttpClientConfiguration] from ClassLoader [sun.misc.Launcher$AppClassLoader @18b4aac2 ] at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java: 481 ) ~[spring-core- 5.2 . 8 .RELEASE.jar: 5.2 . 8 .RELEASE] ...... Caused by: java.lang.NoClassDefFoundError: org/apache/http/impl/client/HttpClientBuilder at java.lang.Class.getDeclaredMethods0(Native Method) ~[na: 1.8 .0_241] ...... ... 21 common frames omitted Caused by: java.lang.ClassNotFoundException: org.apache.http.impl.client.HttpClientBuilder at java.net.URLClassLoader.findClass(URLClassLoader.java: 382 ) ~[na: 1.8 .0_241] ...... ... 25 common frames omitted Process finished with exit code 1 |
这是springcloud 中的依赖,我们发现在这里有两个不同版本的httpclient, 盲猜是低版本的依赖中没有那个类所以与springboot 项目不兼容。打开目录结构果然没有发现 httpClientBuilder
这个类。
引入httpclient 的版本即可
<properties> <httpclient.version>4.5</httpclient.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>${httpclient.version}</version> </dependency> </dependencies> </dependencyManagement>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具