文章目录

  • 一、JAVA 项目中如何实现远程接口调用?
  • 二、什么是Feign
    • 2.2 Feign的优势
    • 2.2 Feign的设计架构与底层原理源码
    • 2.3 Ribbon&Feign对比
      • Ribbon+RestTemplate进行微服务调用
      • Feign进行微服务调用
    • 2.4 Feign单独使用
  • 三、Spring Cloud Alibaba快速整合Feign
  • 四、Spring Cloud Feign的自定义配置及使用
    • 4.1 日志配置
    • 4.2 契约配置
    • 4.3 通过拦截器实现认证
      • 扩展点: feign.RequestInterceptor
      • 自定义拦截器实现认证逻辑
    • 4.4 超时时间配置
    • 4.5 客户端组件配置
      • 4.5.1 配置Apache HttpClient
      • 4.5.2 配置 OkHttp
    • 4.6 GZIP 压缩配置
    • 4.7 编码器解码器配置
      • Java配置方式
      • yml配置方式

一、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和Eureka,从而使得Feign的使用更加方便。

2.2 Feign的优势

Feign可以做到使用 HTTP 请求远程服务时就像调用本地方法一样的体验,开发者完全感知不到这是远程方法,更感知不到这是个 HTTP 请求。它像 Dubbo 一样,consumer 直接调用接口方法调用 provider,而不需要通过常规的 Http Client 构造请求再解析返回数据。它解决了让开发者调用远程接口就跟调用本地方法一样,无需关注与远程的交互细节,更无需关注分布式环境开发。

2.2 Feign的设计架构与底层原理源码

架构设计

Feign+Ribbon的调用流程图:

Feign的源码解析:

2.3 Ribbon&Feign对比

Ribbon+RestTemplate进行微服务调用

@Bean
@LoadBalanced
public RestTemplate restTemplate() {return new RestTemplate();
}//调用方式
String url = "http://mall-order/order/findOrderByUserId/"+id;
R result = restTemplate.getForObject(url,R.class);

Feign进行微服务调用

@FeignClient(value = "mall-order",path = "/order")
public interface OrderFeignService {@RequestMapping("/findOrderByUserId/{userId}")public R findOrderByUserId(@PathVariable("userId") Integer userId);
}@Autowired
OrderFeignService orderFeignService;
//feign调用
R result = orderFeignService.findOrderByUserId(id);

2.4 Feign单独使用

引入依赖:

<dependency><groupId>com.netflix.feign</groupId><artifactId>feign-core</artifactId><version>8.18.0</version>
</dependency>
<dependency><groupId>com.netflix.feign</groupId><artifactId>feign-jackson</artifactId><version>8.18.0</version>
<dependency>

编写接口:

public interface RemoteService {@Headers({"Content-Type: application/json","Accept: application/json"})@RequestLine("GET /order/findOrderByUserId/{userId}")public R findOrderByUserId(@Param("userId") Integer userId);
}

调用:

public class FeignDemo {public static void main(String[] args) {//基于json// encoder指定对象编码方式,decoder指定对象解码方式RemoteService service = Feign.builder().encoder(new JacksonEncoder()).decoder(new JacksonDecoder()).options(new Request.Options(1000, 3500)).retryer(new Retryer.Default(5000, 5000, 3)).target(RemoteService.class, "http://localhost:8020/");System.out.println(service.findOrderByUserId(1));}
}

三、Spring Cloud Alibaba快速整合Feign

1)引入依赖

<!-- openfeign 远程调用 -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2)编写调用接口+@FeignClient注解

@FeignClient(value = "mall-order", path = "/order")
public interface OrderFeignService {@RequestMapping("/findOrderByUserId/{userId}")public R findOrderByUserId(@PathVariable("userId") Integer userId);
}

3)调用端在启动类上添加@EnableFeignClients注解

@SpringBootApplication
@EnableFeignClients
public class MallUserFeignDemoApplication {public static void main(String[] args) {SpringApplication.run(MallUserFeignDemoApplication.class, args);}
}

4)发起调用,像调用本地方式一样调用远程服务

@RestController
@RequestMapping("/user")
public class UserController {@AutowiredOrderFeignService orderFeignService;@RequestMapping(value = "/findOrderByUserId/{id}")public R  findOrderByUserId(@PathVariable("id") Integer id) {//feign调用R result = orderFeignService.findOrderByUserId(id);return result;}
}

提示: Feign 的继承特性可以让服务的接口定义单独抽出来,作为公共的依赖,以方便使用。

四、Spring Cloud Feign的自定义配置及使用

Feign 提供了很多的扩展机制,让用户可以更加灵活的使用。

4.1 日志配置

有时候我们遇到 Bug,比如接口调用失败、参数没收到等问题,或者想看看调用性能,就需要配置 Feign 的日志了,以此让 Feign 把请求信息输出来。

1)定义一个配置类,指定日志级别

// 注意: 此处配置@Configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置
public class FeignConfig {/*** 日志级别** @return*/@Beanpublic Logger.Level feignLoggerLevel() {return Logger.Level.FULL;}
}

注意: 此处配置@Configuration注解就会全局生效,如果想指定对应微服务生效,就不能配置

通过源码可以看到日志等级有 4 种,分别是:

  • NONE【性能最佳,适用于生产】:不记录任何日志(默认值)。
  • BASIC【适用于生产环境追踪问题】:仅记录请求方法、URL、响应状态代码以及执行时间。
  • HEADERS:记录BASIC级别的基础上,记录请求和响应的header。
  • FULL【比较适用于开发及测试环境定位问题】:记录请求和响应的header、body和元数据。

2) 局部配置,让调用的微服务生效,在@FeignClient 注解中指定使用的配置类

3) 在yml配置文件中执行 Client 的日志级别才能正常输出日志,格式是"logging.level.feign接口包路径=debug"

logging:level:com.jihu.mall.user.feign: debug


补充:局部配置可以在yml中配置
对应属性配置类: org.springframework.cloud.openfeign.FeignClientProperties.FeignClientConfiguration

feign:client:config:mall-order:  #对应微服务loggerLevel: FULL

4.2 契约配置

Spring Cloud 在 Feign 的基础上做了扩展,可以让 Feign 支持 Spring MVC 的注解来调用。原生的 Feign 是不支持 Spring MVC 注解的,如果你想在 Spring Cloud 中使用原生的注解方式来定义客户端也是可以的,通过配置契约来改变这个配置,Spring Cloud 中默认的是 SpringMvcContract。

1)修改契约配置,支持Feign原生的注解

/*** 修改契约配置,支持Feign原生的注解* @return*/
@Bean
public Contract feignContract() {return new Contract.Default();
}

注意:修改契约配置后,OrderFeignService 不再支持springmvc的注解,需要使用Feign原生的注解.

2)OrderFeignService 中配置使用Feign原生的注解

@FeignClient(value = "mall-order", path = "/order")
public interface OrderFeignService {@RequestLine("GET /findOrderByUserId/{userId}")public R findOrderByUserId(@Param("userId") Integer userId);
}

3)补充,也可以通过yml配置契约

feign:client:config:mall-order:  #对应微服务loggerLevel: FULLcontract: feign.Contract.Default   #指定Feign原生注解契约配置

4.3 通过拦截器实现认证

通常我们调用的接口都是有权限控制的,很多时候可能认证的值是通过参数去传递的,还有就是通过请求头去传递认证信息,比如 Basic 认证方式。 接口鉴权。

Feign 中我们可以直接配置 Basic 认证

@Configuration  // 全局配置
public class FeignConfig {@Beanpublic BasicAuthRequestInterceptor basicAuthRequestInterceptor() {return new BasicAuthRequestInterceptor("admin", "123456");}
}

当然,这种方式我们一般也不会使用,一般都是自己实现拦截器,实现自己的鉴权逻辑。

扩展点: feign.RequestInterceptor

每次 feign 发起http调用之前,会去执行拦截器中的逻辑。

public interface RequestInterceptor {/*** Called for every request. Add data using methods on the supplied {@link RequestTemplate}.*/void apply(RequestTemplate template);
}

使用场景

  • 统一添加 header 信息;
  • 对 body 中的信息做修改或替换;

自定义拦截器实现认证逻辑

public class FeignAuthRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {// 业务逻辑String access_token = UUID.randomUUID().toString();template.header("Authorization", access_token);}
}@Configuration  // 全局配置
public class FeignConfig {@Beanpublic Logger.Level feignLoggerLevel() {return Logger.Level.FULL;}/*** 自定义拦截器* @return*/@Beanpublic FeignAuthRequestInterceptor feignAuthRequestInterceptor(){return new FeignAuthRequestInterceptor();}
}

测试:

补充:可以在yml中配置

eign:client:config:mall-order:  #对应微服务requestInterceptors[0]:  #配置拦截器com.jihu.mall.user.interceptor.FeignAuthRequestInterceptor

mall-order端可以通过 @RequestHeader获取请求参数.

建议在filter、interceptor中处理。

4.4 超时时间配置

通过 Options 可以配置连接超时时间和读取超时时间,Options 的第一个参数是连接的超时时间(ms),默认值是 2s;第二个是请求处理的超时时间(ms),默认值是 5s。

@Configuration
public class FeignConfig {@Beanpublic Request.Options options() {return new Request.Options(5000, 10000);}
}

yml中配置:

feign:client:config:mall-order:  #对应微服务# 连接超时时间,默认2sconnectTimeout: 5000# 请求处理超时时间,默认5sreadTimeout: 10000

补充说明: Feign的底层用的是Ribbon,但超时时间以Feign配置为准。

测试超时情况:

返回结果:

4.5 客户端组件配置

Feign 中默认使用 JDK 原生的 URLConnection 发送 HTTP 请求,我们可以集成别的组件来替换掉 URLConnection,比如 Apache HttpClient,OkHttp。

Feign发起调用真正执行逻辑:feign.Client#execute (扩展点)

4.5.1 配置Apache HttpClient

引入依赖:

<!-- Apache HttpClient -->
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.7</version>
</dependency>
<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-httpclient</artifactId><version>10.1.0</version>
</dependency>

然后修改yml配置,将 Feign 的 Apache HttpClient启用 :

feign:#feign 使用 Apache HttpClient  可以忽略,默认开启httpclient:enabled: true

关于配置可参考源码: org.springframework.cloud.openfeign.FeignAutoConfiguration
即默认会开启httpClient的配置。所以只要我们引入依赖会自动生效。

测试:调用会进入feign.httpclient.ApacheHttpClient#execute

4.5.2 配置 OkHttp

引入依赖:

<dependency><groupId>io.github.openfeign</groupId><artifactId>feign-okhttp</artifactId>
</dependency>

然后修改yml配置,将 Feign 的 HttpClient 禁用,启用 OkHttp,配置如下:

feign:#feign 使用 okhttphttpclient:enabled: falseokhttp:enabled: true

关于配置可参考源码: org.springframework.cloud.openfeign.FeignAutoConfiguration

测试:调用会进入feign.okhttp.OkHttpClient#execute

4.6 GZIP 压缩配置

开启压缩可以有效节约网络资源,提升接口性能,我们可以配置 GZIP 来压缩数据:

feign:# 配置 GZIP 来压缩数据compression:request:enabled: true# 配置压缩的类型mime-types: text/xml,application/xml,application/json# 最小压缩值min-request-size: 2048response:enabled: true

注意:只有当 Feign 的 Http Client 不是 okhttp3 的时候,压缩才会生效,配置源码在FeignAcceptGzipEncodingAutoConfiguration


核心代码就是 @ConditionalOnMissingBean(type=“okhttp3.OkHttpClient”),表示 Spring BeanFactory 中不包含指定的 bean 时条件匹配,也就是没有启用 okhttp3 时才会进行压缩配置。

4.7 编码器解码器配置

Feign 中提供了自定义的编码解码器设置,同时也提供了多种编码器的实现,比如 Gson、Jaxb、Jackson。我们可以用不同的编码解码器来处理数据的传输。如果你想传输 XML 格式的数据,可以自定义 XML 编码解码器来实现获取使用官方提供的 Jaxb。

**扩展点:Encoder & Decoder **

public interface Encoder {void encode(Object object, Type bodyType, RequestTemplate template) throws EncodeException;
}
public interface Decoder {Object decode(Response response, Type type) throws IOException, DecodeException, FeignException;
}

Java配置方式

配置编码解码器只需要在 Feign 的配置类中注册 Decoder 和 Encoder 这两个类即可:

@Bean
public Decoder decoder() {return new JacksonDecoder();
}
@Bean
public Encoder encoder() {return new JacksonEncoder();
}

yml配置方式

feign:client:config:mall-order:  #对应微服务# 配置编解码器encoder: feign.jackson.JacksonEncoderdecoder: feign.jackson.JacksonDecoder

微服务调用组件Feign实战相关推荐

  1. 【Spring Cloud Alibaba】(二)微服务调用组件Feign原理+实战

    系列目录 [Spring Cloud Alibaba](一)微服务介绍 及 Nacos注册中心实战 本文目录 系列目录 前言 什么是RPC? Feign和OpenFeign都是什么? HTTP调用 v ...

  2. 微服务调用组件Feign:简介以及搭建环境

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  3. 两个子集pom互相调用_声明式服务调用组件Feign

    什么是Feign?    Feign是SpringCloud组件中的一个轻量级RESTful的HTTP服务客户端.Feign内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务. 什么是 ...

  4. Spring cloud alibaba--Feign微服务调用组件

    目录 1.1Feign优势 2.spring cloud alibaba整合Feign 3.Spring Cloud Feign日志配置 4.Feign契约配置 5.Feign超时时间配置 6.Ope ...

  5. 通过Feign实现Spring Cloud微服务调用

    我们在上一篇文章通过restTemplate实现Spring cloud微服务的调用中介绍了spring cloud微服务的一种调用方式,本文我们介绍另一种调用spring cloud微服务的方式-- ...

  6. Feign Hystrix微服务调用Session传播

      在使用SpringCloud来构建微服务时,服务和服务之间的调用非常频繁,服务之间调用通常用feign和Hystrix结合来使用,当使用上游微服务调用下游微服务时,怎么将上游服务的请求信息传递到下 ...

  7. 基于实战开发垂直搜索引擎_基于DDD的微服务设计和开发实战

    作者:欧创新.邓頔.文艺 你是否还在为微服务应该拆多小而争论不休?到底如何才能设计出收放自如的微服务?怎样才能保证业务领域模型与代码模型的一致性?或许本文能帮你找到答案. 本文是基于 DDD 的微服务 ...

  8. ddd 访问权限_基于DDD的微服务设计和开发实战

    作者:欧创新.邓頔.文艺 你是否还在为微服务应该拆多小而争论不休?到底如何才能设计出收放自如的微服务?怎样才能保证业务领域模型与代码模型的一致性?或许本文能帮你找到答案. 本文是基于 DDD 的微服务 ...

  9. 微服务调用链追踪中心搭建 1

    概述 一个完整的微服务系统包含多个微服务单元,各个微服务子系统存在互相调用的情况,形成一个 调用链.一个客户端请求从发出到被响应 经历了哪些组件.哪些微服务.请求总时长.每个组件所花时长 等信息我们有 ...

最新文章

  1. 再见,HttpClient!再见,Okhttp!
  2. US News 2021年世界大学排行榜发布,清华大学首登亚洲第一
  3. 求链表倒数第k个结点
  4. mysql from_unixtime_MySQL 数据库中日期与时间函数 FROM_UNIXTIME(), UNIX_TIME() ...
  5. 操作系统上机作业--创建N个线程(多线程)
  6. HTTP管线化(HTTP pipelining)
  7. C++:49---继承中的友元
  8. windows下安装gcc编译器(c/c++/fortran)
  9. Android高手进阶:Adapter深入理解与优化
  10. 在MT4上使用KDJ指标
  11. C#利用word2007插件实现word转pdf
  12. 不要重启!诺顿居然将系统文件当病毒
  13. 学习笔记(12):Google开发专家带你学 AI:入门到实战(Keras/Tensorflow)(附源码)-深度学习“四件套”:数据、模型、损失函数与优化器
  14. IDEA 创建文件类型与预期文件类型不符时,如何更改
  15. 手机不能打电话没有信号无服务器,手机信号故障排除方法
  16. Windows远程桌面连接保姆级教学
  17. 抖音康辉机器人_新闻联播主持康辉玩抖音,卖萌耍宝样样精通,观众为其点赞...
  18. 弗洛伊德(Floyd)算法详解
  19. H-A + B用于投入产出实践(VIII)
  20. PS制作五彩抽象人像

热门文章

  1. paddleocr自定义字典训练自己的数据集(rec模块)
  2. 聊聊数据指标体系搭建流程
  3. Python项目打包部署Linux服务上
  4. 迷宫之深搜回溯算法(B站)
  5. python使用手册<5>函数
  6. CarMaker 适配 matlab 版本
  7. 2012年2月12日汇报Axure RP Pro 6.5 Beta简体中文加强测试版进展
  8. 异类 不一样的成功启示录
  9. Excel VBA教程–如何使用Visual Basic在电子表格中编写代码
  10. 2级c语言高级应用程序,全国计算机等级考试二级教程-C语言程序设计.pdf