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各种使用技巧说明的更多相关文章

  1. 通过实现仿照FeignClient框架原理的示例来看清FeignClient的本质

    前言 FeignClient的实现原理网上一搜一大把,此处我就不详细再说明,比如:Feign原理 (图解) - 疯狂创客圈 - 博客园 (cnblogs.com),而且关于FeignClient的使用 ...

  2. 编程小技巧之 Linux 文本处理命令

    合格的程序员都善于使用工具,正所谓君子性非异也,善假于物也.合理的利用 Linux 的命令行工具,可以提高我们的工作效率. 本文简单的介绍三个能使用 Linux 文本处理命令的场景,给大家开阔一下思路 ...

  3. 探究javascript对象和数组的异同,及函数变量缓存技巧

    javascript中最经典也最受非议的一句话就是:javascript中一切皆是对象.这篇重点要提到的,就是任何jser都不陌生的Object和Array. 有段时间曾经很诧异,到底两种数据类型用来 ...

  4. 前端极易被误导的css选择器权重计算及css内联样式的妙用技巧

    记得大学时候,专业课的网页设计书籍里面讲过css选择器权重的计算:id是100,class是10,html标签是5等等,然后全部加起来的和进行比较... 我只想说:真是误人子弟,害人不浅! 最近,在前 ...

  5. 前端网络、JavaScript优化以及开发小技巧

    一.网络优化 YSlow有23条规则,中文可以参考这里.这几十条规则最主要是在做消除或减少不必要的网络延迟,将需要传输的数据压缩至最少. 1)合并压缩CSS.JavaScript.图片,静态资源CDN ...

  6. 工欲善其事,必先利其器 之 VS2013全攻略(安装,技巧,快捷键,插件)!

    如有需要WPF工具的朋友可以移步 工欲善其事,必先利其器 之 WPF篇: 随着开发轨迹来看高效WPF开发的工具和技巧 之前一篇<c++的性能, c#的产能?!鱼和熊掌可以兼得,.NET NATI ...

  7. 15个关于Chrome的开发必备小技巧[译]

    谷歌Chrome,是当前最流行且被众多web开发人员使用的浏览器.最快六周就更新发布一次以及伴随着它不断强大的开发组件,使得Chrome成为你必备的开发工具.例如,在线编辑CSS,console以及d ...

  8. Git小技巧 - 指令别名及使用Beyond Compare作为差异比较工具

    前言 本文主要写给使用命令行来操作Git的用户,用于提高Git使用的效率.至于使用命令还是GUI(Tortoise Git或VS的Git插件)就不在此讨论了,大家根据自己的的喜好选择就好.我个人是比较 ...

  9. 【工具使用】mac电脑使用技巧

    本文地址 分享提纲: 1.  mac命令行和finder的交互 2. 一些mac的插件 3. 一些开发的配置 1.mac命令行和findder交互           1)命令行中打开当前文件夹: o ...

随机推荐

  1. 100台机器上海量IP如何查找出现频率 Top 100?

    场景题 有 100 机器,每个机器的磁盘特别大,磁盘大小为 1T,但是内存大小只有 4G,现在每台机器上都产生了很多 ip 日志文件,每个文件假设有50G,那么如果计算出这 100 太机器上访问量最多 ...

  2. Linux 清空日志的五种方法

    VIM 是linux下一款优秀的编辑器,但是上手难度略大,网络上可以找到的教程很多,快捷键也非常多,一时很难记住. 本文换一种思路,就是根据平时自己的常用需要,去反查VIM如何操作的,再记录下来,这样 ...

  3. 数据库MHA原理

    一.数据库的高可用MHA (1):详细的步骤 1.master mysql宕机了,MHA manager :无法连接master 2.MHA在S1 S2找一个延迟最小的slave,确定为未来的mast ...

  4. iOS实现XMPP通讯(一)搭建Openfire

    安装Openfire Openfire官网下载地址:https://igniterealtime.org/downloads/ (也是Spark客户端的下载地址) Openfire下载并安装后,打开系 ...

  5. zabbix和prometheus的优缺点对比

    使用Prometheus(https://github.com/prometheus)原生的k8s服务发现驱动,采集容器化信息:通过微服务参数配置,暴露运行状态信息提供给prometheus,实现微服 ...

  6. 2.1 OOP & SOLID

    OOP & SOLID Implementing DDD highly relies on the Object Oriented Programming (OOP) and SOLID pr ...

  7. 【UE4 C++ 基础知识】<13> 多线程——TaskGraph

    概述 TaskGraph 系统是UE4一套抽象的异步任务处理系统 TaskGraph 可以看作一种"基于任务的并行编程"设计思想下的实现 通过TaskGraph ,可以创建任意多线 ...

  8. dwr简单应用及一个反向ajax消息推送

    由于项目中最近需要用到dwr实现一些功能,因此在网上和dwr官网上找了一些资料进行学习.在此记录一下.(此处实现简单的dwr应用和dwr消息反向推送) 一.引入dwr的包 <dependency ...

  9. Linux资料 帮你理清思路

    很多同学接触linux不多,对linux平台的开发更是一无所知. 而现在的趋势越来越表明,作为一个优秀的软件开发人员,或计算机it行业从业人员,="" 掌握linux是一种很重要的 ...

  10. clone-graph leetcode C++

    Clone an undirected graph. Each node in the graph contains alabeland a list of itsneighbors. OJ's un ...