百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

Feign : 优雅的调用 API feign如何调用

yuyutoo 2024-10-25 19:21 3 浏览 0 评论


前言

在项目开发中,系统间会存在接口调用,在微服务架构中可以使用 Dubbo 来实现服务间的 RPC 调用,也可以使用 Spring Could 完成 API 调用,这些框架屏蔽了 API 调用中的像服务建连、通信协议、序列化等等细节,让开发者可以很轻松发起一个接口调用,但是当需要调用一个外部系统时,由于通信协议、技术框架、网络隔离、安全性等因素,一般会采用原生 HTTP 协议进行接口调用

URLConnection

在 Java 中,JDK 提供了 HTTP 的工具类 URLConnection,通过 URLConnection 可以发起 HTTP 请求,如:

HttpURLConnection connection = null;
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
try {
    connection = (HttpURLConnection)(new URL("http://www.api.com/get")).openConnection();
    connection.connect();
    // 读取接口返回内容
    inputStream = connection.getInputStream();
    inputStreamReader = new InputStreamReader(inputStream);
    bufferedReader = new BufferedReader(inputStreamReader);
    String line = bufferedReader.readLine();
    StringBuffer lines = new StringBuffer();
    while(line != null) {
        line = bufferedReader.readLine();
        lines.append(line);
    }
   
    // 反序列化成 json
    JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity()));
    // TODO
    // jsonObject.get('xx')
    // ……
    
} catch(Exception e) {
    e.printStackTrace();
} finally {
    connection.disconnect();
    if(inputStream != null) inputStream.close();
    if(inputStreamReader != null) inputStreamReader.close();
    if(bufferedReader != null) bufferedReader.close();
}

在不借助任何框架的前提下使用 JDK 自带的类库来发起 HTTP 调用

HttpClient

在实际项目中一般不会使用 JDK 自带的 URLConnection,原因是性能不高,没有连接池,代码也很臃肿,所以一般会使用 HttpClient 来代替 URLConnection,这也是大家比较常见的使用方式,如:

SchemeRegistry schreg = new SchemeRegistry();
schreg.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
PoolingClientConnectionManager conMgr = new PoolingClientConnectionManager(schreg);
conMgr.setMaxTotal(200);// 连接池最大数
conMgr.setDefaultMaxPerRoute(conMgr.getMaxTotal());

// 发起 API 调用
DefaultHttpClient defaultHttpClient = new DefaultHttpClient(conMgr);
HttpGet get = new HttpGet("http://www.api.com/get");
CloseableHttpResponse response = defaultHttpClient.execute(get);

// 反序列化成 json
JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(response.getEntity()));
// TODO
// jsonObject.get('xx')
// ……

EntityUtils.consume(response.getEntity());

一般来说 HttpClient 可以满足日常的开发了,如果是使用 json 作为序列化协议的话,则需要在调用接口和获取接口返回值时分别进行序列化和反序列化操作,这样看似没有问题,但假如当系统中需要调用100个不同的 HTTP 接口,每个接口都需要处理序列化、反序列化以及上面的 HttpClient 相关的代码,代码可读性就非常差,系统的可维护性就低,当然你可以封装 HttpClient 的相关方法,对序列化、反序列化进行泛化封装,提高可读性,此外也有另一种更好的处理方法,使用 Feign 框架,像调用本地方法一样调用 API。

Feign

引入依赖

<dependency>
  <groupId>io.github.openfeign</groupId>
  <artifactId>feign-core</artifactId>
  <version>10.10.1</version>
</dependency>

使用 Feign 调用接口跟调用 RPC 一样,都是先定义 API 的接口

interface API {
    @RequestLine("GET /get")
    @Headers("Content-Type: application/json")
    Response get(Request request);
}

API 接口声明了一个 get 方法,接口的地址为 /get ,同时在 header 头中加入了 Content-Type,Request 作为参数是 get 接口的参数,Response 作为返回值是 get 接口的返回值,Feign 会自动将 Request 对象序列化成 /get 的参数,同时把接口返回值序列化成 Response 对象。

定义好接口后,就可以通过 Feign 来生成 "http://www.api.com" 接口的代理类

API api = Feign.builder()
                .decoder(new JacksonDecoder())
                .encoder(new JacksonEncoder())
                .client(new ApacheHttpClient(HttpClientBuilder.create().setMaxConnPerRoute(100).setMaxConnTotal(500).build()))
                .logger(new Slf4jLogger())
                .addCapability(new Metrics5Capability())
                .retryer(Retryer.NEVER_RETRY)
                .target(Oudianyun.class, "http://www.api.com");

通过 Feign.builder() 为每个域名生成一个 API 代理类,其中序列化协议使用了 json;HTTP 框架使用了 Apache HttpClient,在 Feign 内部最终还是通过 HttpClient 来发送 HTTP 请求,也可以只用 OkHttp;日志使用了 Slf4j

通过 Feign.builder 得到 API 的代理类后,就可以发起接口调用了

// 构建参数
Request request = new Request();
request.setId("abc");
// 调用 get 接口
Response response = api.get(request);

发现没有,使用 Feign 后根据不用关心 HTTP 请求中需要处理的序列化、请求头等硬编码,这些都是 Feign 帮我们实现了,使用时只需要根据不同的域名通过 Feign 来生成代理类,然后跟调用本地方法一样直接调用接口

上面完成简单的 Feign 的使用,在实际开发中这还是远不够的,上面的 API 对象是通过硬编码的方式来创建的,而实际项目中对象一般都是交给 Spring 来管理的,因此最佳的方式是把 Feign 和 Spring 整合

Spring Cloud Feign

Spring Cloud 整合了 Feign,并对其进行改造并将整合内容放到了 spring-cloud-openfeign 模块中,相比原生的 Feign 来说 Spring 容器管理了所有的对象,并对其进行了增强,加入了 fallback机制、负载均衡等特性。

引入依赖

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-openfeign</artifactId>
  <version>2.2.6.RELEASE</version>
</dependency>

跟 Feign 一样,Spring Cloud Feign 也是先定义 API 的接口

@FeignClient(value = "SpringCloudAPI", url ="http://www.api.com", fallback = SpringCloudAPIFallback.class)
interface SpringCloudAPI {
    
    @GetMapping("/get")
    Response get(Request request);
    
}

使用 @FeignClient 注解来声明 url 以及 fallback 降级处理类,当接口出现异常时会调用 SpringCloudAPIFallback 类中的降级方法,降级类如下:

@Component
class SpringCloudAPIFallback implements SpringCloudAPI{
    public Response get(Request request) {
        return "接口出现异常,使用 mock 数据";
    }
}

通过在 Spring Boot 中新增 @EnableFeignClients 开启 Spring Cloud Feign 功能

@SpringBootApplication(scanBasePackages = "feign")
@EnableFeignClients(basePackages = "feign")
public class SpringCloudFeignDemo {
    public static void main(String[] args) {
        new SpringApplication(SpringCloudFeignDemo.class).run(args);
    }
}

Spring Boot 中启用 Feign HttpClient 的参数配置如下:

feign.httpclient.enabled=true
feign.httpclient.connection-timeout=2000
feign.httpclient.connection-timer-repeat=3000
feign.httpclient.max-connections=500
feign.httpclient.max-connections-per-route=500
feign.httpclient.time-to-live=900
feign.httpclient.time-to-live-unit=SECONDS

Spring Could Feign 的 Fallback 是依赖 hystrix 来实现降级的,由于 hystrix 已经不维护了,因此推荐使用 Alibaba 的 Sentinel 来代替 hystrix,加入以下配置启用 Sentinel

引入依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
    <version>2.2.3.RELEASE</version>
</dependency>

开启配置

feign.sentinel.enabled=true

相关推荐

野路子科技!2步教你把手机改造成一个FTP服务器,支持PC互传

哈喽,大家好,我是野路子科技,今天来给大家带来一个教程,希望大家喜欢。正如标题所言,就是教大家如何把售价改造成FTP服务器,而这个时候估计有朋友会问了,把手机改造成FTP服务器有什么用呢?现在有Q...

不得不看:别样于Server-U的群晖文件存储服务器的搭建与使用

我先前的作品中,有着关于Server-U的ftp文件存储服务器的搭建与访问的头条文章和西瓜视频,而且我们通过各种方式也给各位粉丝介绍了如何突破局域网实现真正意义上的公网访问机制技术。关于Server-...

Qt三种方式实现FTP上传功能_qt引入qftp库

FTP协议FTP的中文名称是“文件传输协议”,是FileTransferProtocol三个英文单词的缩写。FTP协议是TCP/IP协议组中的协议之一,其传输效率非常高,在网络上传输大的文件时,经...

Filezilla文件服务器搭建及客户端的使用

FileZilla是一个免费开源的FTP软件,分为客户端版本和服务器版本,具备所有的FTP软件功能。可控性、有条理的界面和管理多站点的简化方式使得Filezilla客户端版成为一个方便高效的FTP客户...

美能达柯美/震旦复印机FTP扫描怎么设置?

好多网友不知道怎么安装美能达/震旦复印机扫描,用得最多是SMB和FTP扫描,相对于SMB来说,FTP扫描安装步骤更为便捷,不容易出问题,不需要设置文件夹共享,所以小编推荐FTP来扫描以美能达机器为例详...

CCD(简易FTP服务器软件)_简单ftp服务器软件

CCD简易FTP服务器软件是一款很方便的FPT搭建工具,可以将我们的电脑快速变成一个FPT服务器。使用方法非常简单,只要运行软件就会自动生效,下载银行有该资源。该工具是不提供操作界面的,其他用户可以输...

Ubuntu系统搭建FTP服务器教程_ubuntu架设服务器

在Ubuntu系统上搭建FTP服务器是文件传输的一个非常实用方法,适合需要进行大量文件交换的场景。以下是一步步指导,帮助您在Ubuntu上成功搭建FTP服务器。1.安装vsftpd软件...

理光FTP扫描设置教程_理光ftp扫描设置方法

此教程主要用来解决WIN10系统下不能使用SMB文件夹扫描的问题,由于旧的SMB协议存在安全漏洞,所以微软在新的系统,WIN8/WIN10/SERVER201220162018里使用了新的SMB传...

纯小白如何利用wireshark学习网络技术

写在前面工欲善其事必先利其器!熟悉掌握一种神器对以后的工作必然是有帮助的,下面我将从简单的描述Wireshark的使用和自己思考去写,若有错误或不足还请批评指正。...

京东买13盘位32GB内存NAS:NAS系统安装设置教程

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:yasden你没有看错,我在京东自营商城购买硬件,组装了一台13盘位,32GB内存的NAS,硬盘有13个盘位!CPU是AMD的5500!本文...

FileZilla搭建FTP服务器图解教程_filezilla server搭建ftp服务器

...

python教程之FTP相关操作_python ftps

ftplib类库常用相关操作importftplibftp=ftplib.FTP()ftp.set_debuglevel(2)#打开调试级别2,显示详细信息ftp.connect(“I...

xftp怎么用,xftp怎么用,具体使用方法

Xftp是一款界面化的ftp传输工具,用起来方便简单,这里为大家分享下Xftp怎么使用?希望能帮到有需要的朋友。IIS7服务器管理工具可以批量管理、定时上传下载、同步操作、数据备份、到期提醒、自动更新...

树莓派文件上传和下载,详细步骤设置FTP服务器

在本指南中,详细记录了如何在树莓Pi上设置FTP。设置FTP可以在网络上轻松地将文件传输到Pi上。FTP是文件传输协议的缩写,只是一种通过网络在两个设备之间传输文件的方法。还有一种额外的方法,你可以用...

win10电脑操作系统,怎么设置FTP?windows10系统设置FTP操作方法

打印,打印,扫描的日常操作是每一个办公工作人员的必需专业技能,要应用FTP作用扫描文件到电脑上,最先要必须一台可以接受文件的FTP服务器。许多软件都需要收费标准进行,但人们还可以应用Windows的系...

取消回复欢迎 发表评论: