持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第27天,点击查看活动详情
JAVA 项目中如何实现接口调用?
1)Httpclient
HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 Http 协议的客户端编程工具包,并且它支持 HTTP 协议最新版本和建议。HttpClient 相比传统 JDK 自带的 URLConnection,提升了易用性和灵活性,使客户端发送 HTTP 请求变得容易,提高了开发的效率。
2)Okhttp
一个处理网络请求的开源项目,是安卓端最火的轻量级框架,由 Square 公司贡献,用于替代 HttpUrlConnection 和 Apache HttpClient。OkHttp 拥有简洁的 API、高效的性能,并支持多种协议(HTTP/2 和 SPDY)。
3)HttpURLConnection
HttpURLConnection 是 Java 的标准类,它继承自 URLConnection,可用于向指定网站发送 GET 请求、POST 请求。HttpURLConnection 使用比较复杂,不像 HttpClient 那样容易使用。
4)RestTemplate WebClient
RestTemplate 是 Spring 提供的用于访问 Rest 服务的客户端,RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法,能够大大提高客户端的编写效率。
上面介绍的是最常见的几种调用接口的方法,我们下面要介绍的方法比上面的更简单、方便,它就是 Feign。
一、什么是Feign
Feign是Netflix开发的声明式、模板化的HTTP客户端,其灵感来自Retrofit、JAXRS-2.0以及WebSocket。Feign可帮助我们更加便捷、优雅地调用HTTP API。
Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。
Spring Cloud openfeign对Feign进行了增强,使其支持Spring MVC注解,另外还整合了Ribbon和Nacos,从而使得Feign的使用更加方便
1-1、优势
Feign可以做到使用 HTTP 请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。它像 Dubbo 一样,consumer 直接调用接口方法调用 provider,而不需要通过常规的 Http Client 构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。
二、Spring Cloud Alibaba快速整合OpenFeign
2-1、引入依赖
<!-- openfeign 远程调用 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2-2、编写调用接口+@FeignClient注解
在服务消费端,添加一个服务接口,添加@FeignClient注解,其中value的值为被调用服务的服务名称,path则为调用的最终服务路径,也就是之前Controller上@RequestMapping注解的路径。
下面的sub方法,可以理解为就是一个原来实现方法的接口,最终实现如下:
2-3、调用端在启动类上添加@EnableFeignClients注解
在启动类上加上@EnableFeignClients注解,否则在实现类中注入StockFeignService就会报错。
2-4、发起调用,像调用本地方式一样调用远程服务
将上面写的添加了@FeignClient注解的StockFeignService的类注入到类中,这样就可以直接调用其下面的方法了,实际上最终实现的原理,就是使用了代理。后面再深剖Feign的时候再进行介绍
2-5、测试
可以看到、这样不用RestTemplate也可以实现服务的调用了。
三、Spring Cloud Feign的自定义配置及使用
Feign 提供了很多的扩展机制,让用户可以 更加灵活的使用。
3-1、日志配置
有时候我们遇到 Bug,比如接口调用失败、参数没收到等问题,或者想看看调用性能,就需要配置 Feign 的日志了,以此让 Feign 把请求信息输出来。
3-1-1、全局日志配置
3-1-1-1、定义一个配置类,指定日志级别
配置一个Feign的日志配置类,需要注意的是类上面的@Configuration,添加之后就针对所有feign添加日志,如果不加那就只能设置局部的feign服务,同时Logger引用的包是Feign.Logger。
通过源码可以看到日志等级有 4 种,分别是:
- NONE【性能最佳,适用于生产】:不记录任何日志(默认值)。
- BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。
- HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
- FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据。
3-1-1-2、在stock-server中添加一个get方法
模拟一个通过ID查询商品库存的服务,通过ULR进行传参
3-1-1-3、在order-service服务消费端,通过feign进行声明
通过声明接口,启动服务发现启动失败,如下:
通过分析可以看到是@PathVariable的问题,在springboot中使用@PathVariable不用写value,但是在使用Feign的时候就需要加上value了,整体写法:@PathVariable(value="id"),完整代码如下:
@RequestMapping("get/{id}")
public String get(@PathVariable(value = "id") String id);
3-1-1-4、控制器调用商品库存服务
3-1-1-5、测试调用库存服务
可以看到已经成功在order-service调用stock-service的服务
这个时候看日志是没有任何输出的,原因是虽然给Feign的日志设置了FULL,但是spring的默认日志级别是info,这样debug级别的日志就无法输出了,因此需要修改一些spring的日志级别,但是又不想修改所有程序,因此旧单独针对api中的添加入职级别
3-1-1-5-1、修改feign接口的日志级别
在配置文件中添加日志级别配置
3-1-1-5-2、再次访问接口,查看日志
这样就可以给所有的feign设置日志级别了
3-1-2、局部配置,让调用的微服务生效,
3-1-2-1、通过配置类设置,在@FeignClient 注解中指定使用的配置类
这时候FeignConfig上面的@Configuration需要去掉
然后再feign服务商添加FeignConfig
3-1-2-1-1、测试
再次访问接口,可以看到仍然可以获得日志,如果此时api包中有其他feign服务,并且没有配置FeignConfig那么就无法输出日志了。
3-1-3、通过配置文件,是局部Feign日志生效
feign:
client:
config:
stock-service: #对应微服务
loggerLevel: FULL