SpringBoot动态Feign服务调用详解

目录
  • 1.Feign传统方式的不足
  • 2.动态Feign
    • 2.1.服务生产者
    • 2.2.动态Feign
    • 2.3.服务消费者
  • 3.总结

1.Feign传统方式的不足

①.在微服务架构中,当我们使用Feign传统方式进行服务调用的时候,需要在每个服务消费者中添加FeignClient接口,编写对应的方法,而且当服务生产者Handler新增方法之后,服务消费者也要在FeignClient接口中添加方法,这样的话,会有些累赘.

那么能不能在调用服务提供者方法的时候,传入生产者服务名称的动态生成FeignClient对象,然后通过一个通用的方法,指定Handler的URL以及参数就可以调用到指定的方法呢?

当然可以!

2.动态Feign

2.1.服务生产者

由于微服务项目创建过程并不是重点,所以后续只展示关键的代码.

Handler方法

@RestController
public class OrderController {
    // 模拟数据库存储数据
    private static Map<String, Object> maps = new HashMap<>(10);
    static {
        maps.put("1", "笔记本");
    }
    @GetMapping(value = "/getOrderById/{oId}")
    public Object getOrderById(@PathVariable(name = "oId") String oid) {
        return maps.get(oid);
    }
    @PostMapping(value = "/addOrder")
    public boolean addOrder(@RequestBody Map<String, String> orderMap) {
        try {
            maps.putAll(orderMap);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
}

2.2.动态Feign

为了方便在多个服务消费者模块中使用动态Feign的功能,可以将动态Feign相关的功能单独抽取出来作为一个公共的模块,之后在服务消费者模块中直接依赖该公共模块即可.

①.pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

②.通用方法

/**
 * Description: 通用接口,里面定义通用方法
 *  注意: 由于服务生产者所有的接口的返回值都是json格式的字符串,
 *         所以这里的通用接口的返回值最好使用String类型!!!
 */
public interface DynamicService {
    /**
     * post方法对应的方法
     * @param url 服务生产者Handler方法请求映射地址
     * @param params 服务生产者Handler方法参数
     * @return
     */
    @PostMapping(value = "{url}")
    String executePostRequest(@PathVariable("url") String url, @RequestBody Object params);
    @GetMapping(value = "{url}")
    String executeGetRequest(@PathVariable("url") String url, @SpringQueryMap Object params);
    @PutMapping(value = "{url}")
    String executePutRequest(@PathVariable("url") String url, @RequestBody Object params);
    @DeleteMapping(value = "{url}")
    String executeDeleteRequest(@PathVariable("url") String url, @RequestBody Object params);
}

②.Feign工厂类

/**
 * Description: FeignClient工厂类,根据服务名称创建FeignClient对象(代理对象)
 */
@Component
public class DynamicFeignClientFactory <T>{
    private FeignClientBuilder feignClientBuilder;
    public DynamicFeignClientFactory(ApplicationContext applicationContext){
        this.feignClientBuilder = new FeignClientBuilder(applicationContext);
    }
    //动态生成feignClient对象(代理对象)
    public T getFeignClient(final Class<T> type,String ServiceID){
        return this.feignClientBuilder.forType(type,ServiceID).build();
    }
}

③.动态FeignClient类

/**
 * Description: 通过FeignClient工厂获取到的FeignClient对象通过指定的请求去调用生产者方法!
 */
@Component
public class DynamicClient {
    @Autowired
    private DynamicFeignClientFactory<DynamicService> dynamicDynamicFeignClientFactory;
    public Object executePostApi(String feignName,String url,Object params){
        DynamicService dynamicService = dynamicDynamicFeignClientFactory.getFeignClient(DynamicService.class,feignName);
        return dynamicService.executePostRequest(url,params);
    }
    public Object executeGetApi(String feignName,String url,Object params){
        DynamicService dynamicService = dynamicDynamicFeignClientFactory.getFeignClient(DynamicService.class,feignName);
        return dynamicService.executeGetRequest(url, params);
    }
    //省略了两个方法...
}

动态Feign一旦定义好之后,不管后续服务生产者中添加加多少Handler方法,这里的代码基本上不需要修改,对于服务消费者来说也不会产生任何影响(有点类似于设计模式里面的"开闭原则");

2.3.服务消费者

①.引入动态Feign模块

<dependency>
            <groupId>com.xp</groupId>
            <artifactId>dynamic-feign</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

②.Handler接口

@RestController
public class UserController {
    //注入动态FeignClient对象
    @Autowired
    private DynamicClient dynamicClient;
    @GetMapping(value = "/getorder/{oid}")
    public Object getOrderById(@PathVariable(value = "oid") String oid) {
        //通过动态FeignClient,指定服务名称,Handler方法URL,参数等信息即可调用生产者对应的方法
        return this.dynamicClient.executeGetApi("cloud-order", "/getOrderById/".concat(oid),new HashMap<>());
    }
    @PostMapping(value = "/addOrder")
    public Object addOrder(@RequestBody Map<String,Object> map){
        return this.dynamicClient.executePostApi("cloud-order", "/addOrder", map);
    }
}

③.启动类

@SpringBootApplication
@EnableDiscoveryClient   //服务治理
@EnableFeignClients //开启Feign功能(不写也可以!)
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class,args);
    }
}

代码完成之后,启动相关的服务,就可以进行测试

3.总结

使用动态Feign方式进行服务调用可以让开发者少写很多代码,使其可以专注于业务本身!

到此这篇关于SpringBoot动态Feign服务调用详解的文章就介绍到这了,更多相关SpringBoot Feign内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot Feign使用教程超全面讲解

    目录 开篇 一.使用 Feign 的示例 1.1 添加依赖 1.2 启用 Feign 1.3 编写 FeignClient 接口 1.4 编写对应的服务端 1.5 调用 FeignClient 二.如何切换 Client 2.1 使用 Apache 的 HTTP Client 2.1.1 添加依赖 2.1.2 配置启用 2.2 使用 OkHttp 2.2.1 添加依赖 2.2.2 配置启用 三.如何修改日志级别 3.1 通过配置文件修改日志级别 3.2 通过配置类修改日志级别 四.如何实现数据压

  • SpringCloud解决Feign异步回调问题(SpringBoot+Async+Future实现)

    目录 一.背景 二.设计方案 三.示例代码 四.实现效果测试 五.总结 近期,需要对之前的接口进行优化,缩短接口的响应时间,但是springcloud中的feign是不支持传递异步化的回调结果的,因此有了以下的解决方案,记录一下,仅供参考. 一.背景 对于一个页面上的所有实例有一个查询权限的接口,同时有四个操作类型的需要查询且接口仅支持单个实例单个操作类型操作. 简单来说,假设实例查询退订权限需要1秒钟,那么四个操作共需4秒钟,一共20个实例的话,那么实际所需时间为80秒. 这样显然是不符合要求

  • SpringBoot整合OpenFeign的坑

    目录 项目集成OpenFegin 集成OpenFegin依赖 实现远程调用 解决问题 问题描述 问题分析 问题解决 最近,在使用SpringBoot+K8S开发微服务系统,既然使用了K8S,我就不想使用SpringCloud了.为啥,因为K8S本身的就提供了非常6的服务注册与发现.限流.熔断.负载均衡等等微服务需要使用的技术,那我为啥还要接入SpringCloud呢?额,说了这么多,在真正使用SpringBoot+K8S这一套技术栈的时候,也会遇到一些问题,比如我不需要使用SpringCloud

  • SpringBoot使用Feign调用其他服务接口

    使用SpringCloud的Feign组件能够为服务间的调用节省编码时间并提高开发效率,当服务本身不复杂时可以单独将该组件拿出使用. 引入依赖 <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign --> <dependency> <groupId>org.springframework.cloud</groupId>

  • springboot单独使用feign简化接口调用方式

    目录 单独使用feign简化接口调用 1.引入maven 2.启动类添加@EnableFeignClients注解 3.像平常一样写一个service接口 4.调用接口 springbootfeign调用方式比较 1.事发原因 2.方式1介绍 3.方式2介绍 4.调用结果测试 5.两种方式对比 6.小结一下 单独使用feign简化接口调用 与HttpClient和RestTemplate相比,使用springcloud的feign调用远程接口更为简便,可以通过配置的方式实现远程接口调用.但是有时

  • SpringBoot 关于Feign的超时时间配置操作

    目录 Feign的超时时间配置 feign 时间设置 Feign调用问题 \ 超时 1.项目结构 2.在其他微服务中 引入clientXX.jar 3.feign调用超时 Feign的超时时间配置 feign 时间设置 contextId: 可以指定为某个接口进行单独的超时设置 @FeignClient(value = "user",contextId ="device") public interface DeviceFeignService { @Request

  • SpringBoot动态Feign服务调用详解

    目录 1.Feign传统方式的不足 2.动态Feign 2.1.服务生产者 2.2.动态Feign 2.3.服务消费者 3.总结 1.Feign传统方式的不足 ①.在微服务架构中,当我们使用Feign传统方式进行服务调用的时候,需要在每个服务消费者中添加FeignClient接口,编写对应的方法,而且当服务生产者Handler新增方法之后,服务消费者也要在FeignClient接口中添加方法,这样的话,会有些累赘. 那么能不能在调用服务提供者方法的时候,传入生产者服务名称的动态生成FeignCl

  • .NET的动态编译与WS服务调用详解

    动态编译与WS服务,有关系么?今天就乱弹一番,如何使用动态编译动态生成WS服务调用的代理类,然后通过这个代理类调用WS服务.    首先,动态编译这玩意在.NET里面是非常简单的,实际上只涉及到两个类型:CodeDomProvider以及CompilerParameters他们都位于System.CodeDom.Compiler命名空间.    以下代码可将源码动态编译为一个程序集:动态编译 复制代码 代码如下: CodeDomProvider provider = CodeDomProvide

  • SpringBoot设置动态定时任务的方法详解

    之前写过文章记录怎么在SpringBoot项目中简单使用定时任务,不过由于要借助cron表达式且都提前定义好放在配置文件里,不能在项目运行中动态修改任务执行时间,实在不太灵活. 经过网上搜索学习后,特此记录如何在SpringBoot项目中实现动态定时任务. 因为只是一个demo,所以只引入了需要的依赖: <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <ar

  • SpringBoot使用Shiro实现动态加载权限详解流程

    目录 一.序章 二.SpringBoot集成Shiro 1.引入相关maven依赖 2.自定义Realm 3.Shiro配置类 三.shiro动态加载权限处理方法 四.shiro中自定义角色与权限过滤器 1.自定义uri权限过滤器 zqPerms 2.自定义角色权限过滤器 zqRoles 3.自定义token过滤器 五.项目中会用到的一些工具类常量等 1.Shiro工具类 2.Redis常量类 3.Spring上下文工具类 六.案例demo源码 一.序章 基本环境 spring-boot 2.1

  • Java远程调用组件Feign技术使用详解

    目录 一. 概要 二. Feign简介 1. 概念 2. 功能 三. 服务提供者 1. 添加依赖 2. 配置文件 3. 启动类 4. 控制层 5. POJO 四. 服务消费者 1. 添加依赖 2. 配置文件 3. 启动类 4. Feign服务 5. 控制层 五. 测试 1. 测试get请求 2. 测试post请求json数据格式 3. 测试头部中包含信息 一. 概要 我们知道,现在最火且最有技术含量的技术莫过于SpringCloud微服务了,所以今天壹哥就带大家来学习一下微服务的核心的组件之一,

  • SpringBoot整合多个Mq服务做法详解

    目录 1.自定义一个MqTemplate 2.定义一个mq配置项相对应的类 3.将我们自定义的mq配置定义成MqTemplate类型的bean 4.使用对应的Template发送消息 以rabbitmq为例 springboot项目想要整合rabbitmq非常简单,只需要在maven中引入对应的starter即可 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spri

  • SpringCloud服务的发现与调用详解

    目录 前言 一.服务提供者 二.服务消费者 总结 相关推荐 上一章:Eureka注册中心 前言 上一章中,我们介绍了Eureka注册中心及集群的搭建,这一节将介绍服务的发现和调用.注意,这个时候我们只有注册中心,并没有引入其他的组件,所以需要使用SpringCloud原生态的服务发现和调用的方式实现,循序渐进的带你走入微服务的世界. 上篇文章我们已经创建好了注册中心,这次我们需要创建一个服务提供者(provider)和一个服务消费者(consumer)两个项目. 一.服务提供者 新建Maven项

  • Java探索之Feign入门使用详解

    一,简介 Feign使得 Java HTTP 客户端编写更方便.Feign 灵感来源于Retrofit.JAXRS-2.0和WebSocket.Feign最初是为了降低统一绑定Denominator到HTTP API的复杂度,不区分是否支持Restful.Feign旨在通过最少的资源和代码来实现和HTTP API的连接.通过可定制的解码器和错误处理,可以编写任意的HTTP API. Maven依赖: <!-- https://mvnrepository.com/artifact/com.netf

  • Java nacos动态配置实现流程详解

    目录 一.前言 二.在nacos上创建配置文件 创建配置文件 配置说明 发布并检查配置文件 三. 修改项目配置与动态读取配置文件 添加 nacos 动态配置依赖 在controller与service中使用动态配置 四. 动态配置网关的使用 一.前言 使用动态配置的原因: properties 和 yaml 是写到项目中的,好多时候有些配置需要修改,每次修改就要重新启动项目,不仅增加了系统的不稳定性,也大大提高了维护成本,非常麻烦,且耗费时间. 使用动态配置,则可以避免这些麻烦,可以动态的修改配

  • SpringBoot整合Shiro的代码详解

    shiro是一个权限框架,具体的使用可以查看其官网 http://shiro.apache.org/  它提供了很方便的权限认证和登录的功能. 而springboot作为一个开源框架,必然提供了和shiro整合的功能!接下来就用springboot结合springmvc,mybatis,整合shiro完成对于用户登录的判定和权限的验证. 1.准备数据库表结构 这里主要涉及到五张表:用户表,角色表(用户所拥有的角色),权限表(角色所涉及到的权限),用户-角色表(用户和角色是多对多的),角色-权限表

随机推荐