• 微服务实战声明式服务调用OpenFeign实践


    上一篇 微服务实战|负载均衡组件及源码分析

    文章目录

    OpenFeign介绍

    一开始,我们使用原生的 DiscoveryClient 发现服务和使用RestTemplate进行服务间调用,然后我们自己手动开发了一个负载均衡组件,最后介绍了负载均衡组件Ribbon。每个章节调用服务的方式也有所不同,共同点则是都是基于RestTemplate 来实现的,想必大家都会觉得这样的调用方式有点麻烦,每次调用前都要写请求协议,服务名称,接口名称、组装参数、处理响应数据类型,这些都是一些重复的工作,代码也都高度相似,每次请求只有 URL 不同,请求方法不同、参数不同,其它东西基本都是一样的,既然如此,那有没有办法简化请求呢?本文我们要聊的声明式微服务调用OpenFeign 。

    OpenFeign是一个显示声明式的WebService客户端。使用OpenFeign能让编写Web Service客户端更加简单。使用时只需定义服务接口,然后在上面添加注解。OpenFeign也支持可拔插式的编码和解码器。spring cloud对feign进行了封装,使其支持MVC注解和HttpMessageConverts。和eureka(服务注册中心)和ribbon组合可以实现负载均衡。在Spring Cloud中使用OpenFeign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求,非常的方便

    • OpenFeign的设计宗旨式简化Java Http客户端的开发。Feign在restTemplate的基础上做了进一步的封装,由其来帮助我们定义和实现依赖服务接口的定义。在OpenFeign的协助下,我们只需创建一个接口并使用注解的方式进行配置(类似于Dao接口上面的Mapper注解)即可完成对服务提供方的接口绑定,大大简化了Spring cloud Ribbon的开发,自动封装服务调用客户端的开发量。
    • OpenFeign集成了Ribbon,利用ribbon维护了服务列表,并且通过ribbon实现了客户端的负载均衡。与ribbon不同的是,通过OpenFeign只需要定义服务绑定接口且以申明式的方法,优雅而简单的实现了服务调用。

    项目实战

    创建项目

    接下来,就开始我们的项目实战,创建两个服务,一个是dms(就是码表服务,提供各种下拉选项列表),一个是应用系统app(实际的业务系统)

    首先创建名为dms的maven项目,引入依赖

     
            
                org.springframework.boot
                spring-boot-starter-web
            
    
            
                org.springframework.cloud
                spring-cloud-starter-netflix-eureka-client
            
    
            
                org.springframework.cloud
                spring-cloud-starter-openfeign
            
    
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    创建配置文件:

    server:
      port: 8003
    spring:
      application:
        name: dms
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8001/eureka/
    
    logging:
      pattern:
        console: '%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{15} - %msg%n'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    编写启动类

    /**
     * @Author:公众号:程序员965
     * @create 2022-06-20
     **/
    @EnableDiscoveryClient
    @EnableFeignClients
    @EnableEurekaClient
    @SpringBootApplication
    public class DmsApplication {
        public static void main(String[] args) {
            SpringApplication.run(DmsApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    注意此时,我们在启动类上面增加了@EnableFeignClients和@EnableDiscoveryClient注解。

    编写api模块代码,注意这是一个接口对外提供服务,接口的服务名称是dms,根据code代码值获取名称:

    /**
     * @Author:公众号:程序员965
     * @create 2022-06-20
     **/
    @FeignClient(value = "dms")
    public interface DmsApi {
        @RequestMapping(value="/dict/{code}", method = RequestMethod.GET)
        public String findNameByCode(@PathVariable("code") String code);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    编写controller类,可以实现DmsApi接口,这里简单以性别举例:

    /**
     * @Author:公众号:程序员965
     * @create 2022-06-20
     **/
    @RestController
    public class DmsController implements DmsApi {
    
        @Override
        public String findNameByCode(String code) {
            switch (code){
                case "0" :
                    return "男";
                case "1" :
                    return "女";
                default:
                    return "未知";
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    dms模块就开发完毕了。

    同样的,创建app模块,注意需要引入dms模块,以便调用其接口

    
    
            
                com.cxy965
                dms
                ${project.version}
            
    
            
                org.springframework.boot
                spring-boot-starter-web
            
    
            
                org.springframework.cloud
                spring-cloud-starter-netflix-eureka-client
            
            
                org.springframework.boot
                spring-boot-starter-data-jpa
            
    
            
                javax.servlet
                javax.servlet-api
            
    
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    创建controller层:在此注入dmsApi,并通过dmsApi调用其findNameByCode()方法,即可完成服务的调用代码!

    /**
     * @Author:公众号:程序员965
     * @create 2022-06-20
     **/
    @RestController
    public class AppController {
        @Autowired
        private DmsApi dmsApi;
    
        @RequestMapping("/index")
        public String index(){
            String nameByCode = dmsApi.findNameByCode("1");
            return nameByCode;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    启动类

    /**
     * @Author:公众号:程序员965
     * @create 2022-06-20
     **/
    @EnableEurekaClient
    @SpringBootApplication
    public class AppApplication {
        public static void main(String[] args) {
            SpringApplication.run(AppApplication.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    启动项目验证

    在这里插入图片描述

    返回了正确的结果,当注册中心有多个dms服务时,调用时会自动起到负载均衡的作用。

    总结

    OpenFeign 是 Spring Cloud 家族的一个成员, 它最核心的作用是为 HTTP 形式的 Rest API 提供了非常简洁高效的 RPC 调用方式。 如果说 Spring Cloud 其他成员解决的是系统级别的可用性,扩展性问题, 那么 OpenFeign 解决的则是与开发人员利益最为紧密的开发效率问题。这篇文章中我们学会了Feign组件的集成和基础使用,下一篇文章将写一下Feign的更多用法,一起期待吧!

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    ProGAN 论文精读
    2024-04-24 问AI: 在深度学习中,CUDA 是什么?
    Python 元类详解
    实时数仓:实时数据平台之设计篇
    通过区域指针实现PLC和HMI精智触摸屏的通信状态诊断的具体方法
    ATtiny88初体验(二):呼吸灯
    LeetCode经典算法题 no.118杨辉三角
    2023/11/15JAVA学习(线程池,Executors,网络编程,InetAddress,UDP,TCP,DatagramSocket)
    C++数组长度*必须*是编译时已知的?
    主键约束!
  • 原文地址:https://blog.csdn.net/m0_67393619/article/details/126081199