• 声明式调用 —— SpringCloud OpenFeign


    Feign 简介

    Spring Cloud Feign 是一个 HTTP 请求调用的轻量级框架,可以以 Java 接口注解的方式调用 HTTP 请求,而不用通过封装 HTTP 请求报文的方式直接调用

    Feign 通过处理注解,将请求模板化,当实际调用的时候传入参数,根据参数再应用到请求上,进而转化成真正的请求


    第一个 Feign 程序

    本小节介绍如何通过 Nacos+Feign 实现服务之间的调用,新建 server-01、server-02 项目,并分别注册 Nacos

    server-01 引入依赖

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-openfeignartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-loadbalancerartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    新建 Server02FeignClient 接口,用于调用 server-02 提供的对外接口

    // name:要调用的服务名
    FeignClient(name = "server-02")
    public interface Server02FeignClient {
    
        @GetMapping("/test/getConfig")
        void getConfig();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    启动类加上注解 @EnableFeignClients

    @EnableFeignClients
    @EnableDiscoveryClient
    @SpringBootApplication
    public class Server01Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Server01Application.class, args);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    使用 Server02FeignClient 调用 server-02 的接口

    @Slf4j
    @RestController
    public class TestCon {
        
        @Autowired
        private Server02FeignClient server02FeignClient;
    
        @GetMapping("/test/getConfigByFeign")
        public void getConfigByFeign() {
            server02FeignClient.getConfig();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在 server-02 创建接口

    @Slf4j
    @RestController
    public class TestCon {
    
        @Value("${test.value}")
        private String testValue;
    
        @Value("${spring.application.name}")
        private String applicationName;
    
        @Value("${server.port}")
        private String port;
    
        @GetMapping("/test/getConfig")
        public void getConfig() {
            log.info("testValue: {} by {}-{}", testValue, applicationName, port);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    调用 server-01 的 /test/getConfigByFeign 接口,就会通过 Feign 调用 server-02 的 /test/getConfig 接口

    @FeignClient 注解可作用在类、接口、枚举上,主要包含如下属性:

    • name/value:name 是 vaue 的别名,value 也是 name 的别名,两者的作用是一致的,用指定 FeignClient 的名称,如果配合注册中心使用,则作为微服务的名称,用于服务发现

    • url:主要用于调试,可以手动指定 @FeignClient 调用的地址

    • path:path 用于定义当前 FeignClient 的统一前缀

    • contextld:如果要创建多个具有相同名称或 URL 的 Feign 客户端,以便它们指向同一台服务器,但是每个客户端具有不同的自定义配置,则必须使用 contextId 属性,以避免这些配置的名称冲突

    @FeignClient(contextId = "fooClient", name = "stores", configuration=FooConfiguration.class)
    public interface FooClient {...}
    
    @FeignClient(contextId = "barClient", name = "stores", configuration=BarConfiguration.class)
    public interface BarClient {...}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • fallback/fallbackFactory:

    • fallback:定义容错的处理类,当调用远程接口失败或超时时,就会调用对应接口的容错逻辑,falback 指定的类必须实现 @FeignClient 标记的接口

    • fallbackFactory:工厂类,用于生成 fallback 类,通过该属性可以实现每个接口通用的容错逻辑,减少重复的代码

    • decode404:当发生 404 错误时,如果该字段为 true,就会调用 decoder 进行解码,否则抛出异常

    • Configuration:Feign 配置类可以自定义 Feign 的 Encoder、Decoder、LogLevel、Contract 等,OpenFeign 默认为 Feign 提供以下对象(bean 类型 bean 名称 : 类名称):

    • Decoder feignDecoder : ResponseEntityDecoder

    • Encoder feignEncoder : SpringEncoder

    • Logger feignLogger : Slf4jLogger

    • Contract feignContract : SpringMvcContract

    • FeignBuilder feignBuilder : HystrixFeignBuilder

    spring-cloud-starter-openfeign 支持 spring-cloud-starter-netflix-ribbon 和 spring-cloud-starter.loadbalancer,如果 Ribbon 在类路径中且已启用,则 Client feignClient 是 LoadBalancerFeignClient,如果 SpringCloud LoadBalancer 在类路径中,则使用 FeignBlockingLoadBalancerClient

    默认情况下,Spring Cloud OpenFeign 不会为 Feign 提供以下 bean 对象,但是仍然会从应用程序上下文中查找这些类型的 bean 以创建 Feign 客户端:

    • Logger.Level
    • Retryer
    • ErrorDecoder
    • Request.Options
    • Collection
    • SetterFactory
    • QueryMapEncoder

    以上是通过注解 @FeignClient 的配置属性进行配置的,我们也可以使用配置文件进行配置

    feign:
        client:
            config:
                feignName:
                    connectTimeout: 5000
                    readTimeout:5000
                    loggerLevel: full
                    errorDecoder: com.example.SimpleErrorDecoder
                    retryer: com.example,SimpleRetryer
                    requestInterceptors:
                        - com.example.FooRequestInterceptor
                        - com.example,BarRequestInterceptor
                    decode404: false
                    encoder: com.example.SimpleEncoder
                    decoder: com.example.SimpleDecoder
                    contract: com.example.SimpleContract
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    可以在 @EnableFeignClients 属性 defaultConfiguration 中指定默认配置,不同之处在于此配置将适用于所有 Feign 客户端

    如果希望使用配置文件来配置所有 @FeignClient,则可以使用默认 Feign 名称创建配置属性,例如:

    feign:
        client:
            config:
                default:
                    connectTimeout: 5000
                    readTimeout: 5000
                    loggerLevel: basic
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    如果同时创建 @Configuration bean 和配置文件,则配置文件将覆盖 @Configuration 值,如果要将优先级更改为 @Configuration,就可以将 feign.client.default-to-properties 更改为 false


    Feign 传参

    以下服务端接口可通过 Get 或 Post 请求调用并接收参数

    @RequestMapping("/test/testFeignWithParam")
    public void testFeignWithParam(@RequestParam String name,
                                   @RequestParam int age) {
        log.info("testFeignWithParam: name-{}, age-{}", name, age);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    通过在 Url 拼接请求传参如下:

    @FeignClient(name = "server-02", path = "server-02")
    public interface Server02FeignClient {
    
        @GetMapping("/test/testFeignWithParam?name=zhanghsan&age=66")
        //@PostMapping("/test/testFeignWithParam?name=zhanghsan&age=66")
        void testFeignWithParam();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用 @RequestParam 传参如下:

    @FeignClient(name = "server-02", path = "server-02")
    public interface Server02FeignClient {
        
        //@GetMapping("/test/testFeignWithParam")
        @PostMapping("/test/testFeignWithParam")
        void testFeignWithParam(@RequestParam("name") String name,
                                @RequestParam("age") int age);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    也可以使用 OpenFeign 的 @QueryMap 将请求实体作为参数的映射,不过由于 @QueryMap 注解与 Spring 不兼容,所以 OpenFeign 提供了等效的 @SpringQueryMap 注解

    @FeignClient(name = "server-02", path = "server-02")
    public interface Server02FeignClient {
        
        //@GetMapping("/test/testFeignWithQueryMap")
        @PostMapping("/test/testFeignWithQueryMap")
        void testFeignWithQueryMap(@SpringQueryMap FeignParam param);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    java date操作
    抖音短视频SEO是什么?抖音SEO系统源码/SEO系统源码搭建/
    LeetCode每日一题(1648. Sell Diminishing-Valued Colored Balls)
    9.25 day 2
    MongoDB基础运维
    @Redis--主从复制
    精读《精通 console.log》
    青少年软件编程C++二级真题(202106)
    RealVCN连接超时怎么解决
    274. H 指数
  • 原文地址:https://blog.csdn.net/CSDN_handsome/article/details/133433803