feignclient各种使用技巧说明
FeignClient常见用法
常规的FeignClient的创建与使用我相信只要使用过spring cloud全家桶的套件的基本上都是非常熟悉了,我们只需定义一个interface,然后定义相关的远程接口方法签名及在方法上标记相关的请求映射的注解指明请求URL及方式,最后在该接口类上方标记@FeignClient注解,并设置相关参数即可,示例模板如下所示:
/**
* 自定义一个FeignClient标准接口类
* @author zuowenjunn.cn
*/
@FeignClient(name = "baidu",url = "http://www.baidu.com")
public interface DemoFeignClient {
@RequestMapping(value = "/s",produces ="text/html",consumes = "text/html")
String searchBaiDu(@RequestParam("wd") String wd);
}
用法就比较简单了,直接把上述标记为@FeignClient的接口类(如:DemoFeignClient)当成普通BEAN的接口进行依赖注入即可,如下示例代码:
@Autowired
private DemoFeignClient demoFeignClient;
String searchResultResp = demoFeignClient.searchBaiDu("梦在旅途");
System.out.println("searchBaiDu Result:" + searchResultResp);
注意了,如上述示例代码均只是为了便于演示而创建的,确实可以拿来(复制到JAVA的spring cloud项目中)即可执行,但实际生产项目中使用则应根据实际的微服务的名称及URL来灵活配置,具体配置与使用可参见我(梦在旅途)之前的文章:玩转Spring Cloud之服务注册发现(eureka)及负载均衡消费(ribbon、feign)
上述通过定义接口+@FeignClient注解的方式是最常见也是最简单的使用的方式,那大家知悉原理吗?其实原理我在之前文章也讲过,核心点就是:在Spring IOC容器初始化时,会通过@EnableFeignClients中的@Import(FeignClientsRegistrar.class)最终执行FeignClientsRegistrar.registerBeanDefinitions方法,把所有标记有@FeignClient注解的接口包装成FeignClientFactoryBean并注册为BEAN,当项目中实际依赖FeignClient接口类时,则会通过FeignClientFactoryBean.getObject来生成真实的FeignClient接口的实现类BEAN,详细源码解读可参见:https://blog.csdn.net/forezp/article/details/83896098 这里面最关键的其实就是FeignClientFactoryBean.getObject方法,而这个方法本质又是调getTarget方法,这个方法最终返回的就是一个Targeter接口的实现类。如果我们想动态自定义一个FeignClient接口,增加一些自定义的逻辑(比如:额外装饰一些逻辑),那么我们只需要自行创建Targeter接口的实现类即可。这种方案是可行的,而且框架也提供了这种自定义的扩展能力:Feign.Builder,Feign.Builder类就是可以实现动态构建FeignClient的利器,下面我将基于这种思路实现动态自定义构建FeignClient。
动态自定义构建FeignClient实现方式一(直接指明服务的URL地址【如果是实际项目中这应该是网关的负载均衡地址哦】)
/**
* 自定义一个FeignClient接口类,除了不用加@FeignClient注解外,其余均相同
* @author zuowenjunn.cn
*/
public interface CustomApiFeignClient {
@RequestMapping(value = "/s",produces ="text/html",consumes = "text/html")
String searchBaiDu(@RequestParam("wd") String wd);
}
/**
* 定义配置类,集中动态配置自定义的FeignClient代理类BEAN
* @author zuowenjun.cn
*/
@Configuration
@Import(FeignClientsConfiguration.class)
public class FeignClientConfig {
@Bean
public CustomApiFeignClient customApiFeignClient(Contract contract, Decoder decoder, Encoder encoder) {
return Feign.builder().contract(contract).encoder(encoder).decoder(decoder).target(CustomApiFeignClient.class, "http://www.baidu.com");
}
}
用法就比较简单了,如常规用法一样,把视为FeignClient接口(如:CustomApiFeignClient)依赖注入到相关的BEAN中即可,代码如下所示:
CustomApiFeignClient feignClient = SpringUtils.getBean(CustomApiFeignClient.class); //这里使用工具类获取BEAN,当然也可以使用@Autowired注解方式获得
String searchResultResp = feignClient.searchBaiDu("梦在旅途");
System.out.println("searchBaiDu Result:" + searchResultResp);
动态自定义构建FeignClient实现方式二(直接指明服务名,并进行装饰,支持自定义负载均衡、更换请求API的组件等功能)
/**
* 自定义一个FeignClient接口类,除了不用加@FeignClient注解外,其余均相同
* @author zuowenjunn.cn
*/
public interface CategoryTreeConfigFeignClient {
@RequestMapping(value = "/categoryTreeConfig/getCategoryInfo", method = RequestMethod.POST)
ResponseData<Object> getCategoryInfo(CategoryTreeConfigBO categoryTreeConfigBO);
}
/**
* 定义配置类,集中动态配置自定义的FeignClient代理类BEAN
* @author zuowenjun.cn
*/
@Configuration
@Import(FeignClientsConfiguration.class)
public class FeignClientConfig {
@Bean
public CustomApiFeignClient customApiFeignClient(Contract contract, Decoder decoder, Encoder encoder) {
return Feign.builder().contract(contract).encoder(encoder).decoder(decoder).target(CustomApiFeignClient.class, "http://www.baidu.com");
}
@Bean
public CategoryTreeConfigFeignClient categoryTreeConfigFeignClient(@Qualifier("feignClient") Client client, SpringClientFactory clientFactory, Contract contract, Decoder decoder, Encoder encoder) {
Client customClient = new Client.Default(null, null) {
@Override
public Response execute(Request request, Request.Options options) throws IOException {
return super.execute(request, options);
}
@Override
public HttpURLConnection getConnection(URL url) throws IOException {
String serviceName = url.getHost();
String rawUrl= url.toString();
List<Server> upServers= clientFactory.getLoadBalancer(serviceName).getReachableServers();
//TODO:自定义客户端负载均衡策略,这里只是举例选第1个
Server bestServer= upServers.stream().findFirst().orElse(null);
Assert.notNull(bestServer,serviceName +":从注册中心没有找到可用的Server实例.");
url=new URL(url.getProtocol(),bestServer.getHost(),bestServer.getPort(),url.getFile());
return super.getConnection(url);
}
};
return Feign.builder().client(customClient).contract(contract).encoder(encoder).decoder(decoder).target(CategoryTreeConfigFeignClient.class, "http://微服务名");
}
}
实际用法与上述实现方式一相同,如下:
CategoryTreeConfigFeignClient categoryTreeConfigFeignClient=SpringUtils.getBean(CategoryTreeConfigFeignClient.class);//这里使用工具类获取BEAN,当然也可以使用@Autowired注解方式获得
ResponseData<Object> responseData= categoryTreeConfigFeignClient.getCategoryInfo(new CategoryTreeConfigBO(){
{
setId("50");
setIncludeChild(0);
}
});
除了上述通过Feign.builder()的方式来直接进行额外自定义处理处,还可以在常规用法的基础上增加个性化配置的方式来实现,即:给@FeignClient注解属性configuration赋值自定义的配置类,在配置类中可以定义相关的BEAN以替换全局默认的BEAN,具体方法请参见网上的相关文章介绍。
feignclient各种使用技巧说明的更多相关文章
- 通过实现仿照FeignClient框架原理的示例来看清FeignClient的本质
前言 FeignClient的实现原理网上一搜一大把,此处我就不详细再说明,比如:Feign原理 (图解) - 疯狂创客圈 - 博客园 (cnblogs.com),而且关于FeignClient的使用 ...
- 编程小技巧之 Linux 文本处理命令
合格的程序员都善于使用工具,正所谓君子性非异也,善假于物也.合理的利用 Linux 的命令行工具,可以提高我们的工作效率. 本文简单的介绍三个能使用 Linux 文本处理命令的场景,给大家开阔一下思路 ...
- 探究javascript对象和数组的异同,及函数变量缓存技巧
javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...
- 前端极易被误导的css选择器权重计算及css内联样式的妙用技巧
记得大学时候,专业课的网页设计书籍里面讲过css选择器权重的计算:id是100,class是10,html标签是5等等,然后全部加起来的和进行比较... 我只想说:真是误人子弟,害人不浅! 最近,在前 ...
- 前端网络、JavaScript优化以及开发小技巧
一.网络优化 YSlow有23条规则,中文可以参考这里.这几十条规则最主要是在做消除或减少不必要的网络延迟,将需要传输的数据压缩至最少. 1)合并压缩CSS.JavaScript.图片,静态资源CDN ...
- 工欲善其事,必先利其器 之 VS2013全攻略(安装,技巧,快捷键,插件)!
如有需要WPF工具的朋友可以移步 工欲善其事,必先利其器 之 WPF篇: 随着开发轨迹来看高效WPF开发的工具和技巧 之前一篇<c++的性能, c#的产能?!鱼和熊掌可以兼得,.NET NATI ...
- 15个关于Chrome的开发必备小技巧[译]
谷歌Chrome,是当前最流行且被众多web开发人员使用的浏览器.最快六周就更新发布一次以及伴随着它不断强大的开发组件,使得Chrome成为你必备的开发工具.例如,在线编辑CSS,console以及d ...
- Git小技巧 - 指令别名及使用Beyond Compare作为差异比较工具
前言 本文主要写给使用命令行来操作Git的用户,用于提高Git使用的效率.至于使用命令还是GUI(Tortoise Git或VS的Git插件)就不在此讨论了,大家根据自己的的喜好选择就好.我个人是比较 ...
- 【工具使用】mac电脑使用技巧
本文地址 分享提纲: 1. mac命令行和finder的交互 2. 一些mac的插件 3. 一些开发的配置 1.mac命令行和findder交互 1)命令行中打开当前文件夹: o ...
随机推荐
- 使用 Vue 脚手架,为什么要学 webpack?
先问大家一个很简单的问题: vue init webpack prjectName 与 vue create projectName 有什么区别呢? 它们是 Vue-cli 2 和 Vue-cli3 ...
- 深度学习--GAN学习笔记
生成模型 WGAN Blog GAN 推荐学习网站 生成模型 什么是生成模型? GMM: 用来做聚类,(非监督学习) NB(朴素贝叶斯):(监督学习,可以用来做垃圾邮件分类) Logistics 回归 ...
- 产生UUID随机字符串工具类
产生UUID随机字符串工具类 UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.通常平台会提供生成的API.按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址. ...
- iframe、SameSite与CEF
iframe.SameSite与CEF 背景 本人使用CEF(或是Chrome)来加载开发的前端页面,其中使用iframe嵌入了第三方页面,在第三方页面中需要发送cookie到后端,然而加载会报错,第 ...
- mysql-router-MIC-8.0.26集群部署
1.具体部署详情请看视频 https://space.bilibili.com/677825194 2.mysql主要配置如下 cat > /etc/my.cnf <<EOF [cl ...
- Java初步学习——2021.10.09每日总结,第五周周六
(1)今天做了什么: (2)明天准备做什么? (3)遇到的问题,如何解决? 今天学习了菜鸟教程实例部分 一.字符串 1.字符串比较--compareTo方法 public class Main { p ...
- 洛谷3233 HNOI2014(虚树+dp)
膜拜一发\(mts\_246,forever\_shi\) 这两位爷是真的无敌! 首先来看这个题,一看题目的数据范围和"关键点"字眼,我们就能得知这是一道虚树题 那就先一如既往的建 ...
- 从零到熟悉,带你掌握Python len() 函数的使用
摘要:本文为你带来如何找到长度内置数据类型的使用len() 使用len()与第三方数据类型 提供用于支持len()与用户定义的类. 本文分享自华为云社区<在 Python 中使用 len() 函 ...
- 爬虫逆向基础,理解 JavaScript 模块化编程 webpack
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! 简介 在分析一些站点的 JavaScript 代码时,比较简单的代码,函数通常都是一个一个的,例 ...
- Google Object detection配置与使用
Google Object detection 前言: 本文记录了使用Google发布的Object detection(July 1st, 2019)接口,完成了对标注目标的检测.参考了很多博文,在 ...