zoukankan      html  css  js  c++  java
  • 5、Spring-Cloud-声明式调用 Feign(上)

     5.1、写一个 Feign 害户端

    新建项目:

     依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    关于服务中心使用的是8762(之前的案列写过)

    地址:https://www.cnblogs.com/Mrchengs/p/10645911.html

     
    配置文件:
    spring.application.name=feign
    server.port=8088
    eureka.client.service-url.defaultZone=http://localhost:8762/eureka/
     
    主配置类:

    @EnableFeignClients:开启Feign Client功能

    @EnableFeignClients(basePackages = "com.cr.eurekafeignclient.feign")
    @EnableDiscoveryClient
    @SpringBootApplication
    public class EurekaFeignClientApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(EurekaFeignClientApplication.class, args);
        }
    }
    上述的三个步骤已经开启了Feign的功能
     
    实现之前eureka client的/port服务的调用

    EurekaClientFeign.java

    @FeignClient(value = "CLINET",configuration = feignconfig.class)
    public interface EurekaClientFeign {
        @GetMapping("/port")
        String port();
    
    }
    @FeignClient:
    value:远程调用其他服务的服务名
    feignconfig.class为Feign Client的配置类
    port():通过Feign来调用CLIENT服务的“/port”的API接口

    feignconfig.java

    @Configuration
    public class feignconfig {
    
        @Bean
        public Retryer feignRetryer(){
            return  new Retryer.Default(100, TimeUnit.SECONDS.toMillis(1L),5);
        }
    }
    配置类:注入一个feignRetryer的Retryer的Bean
    注入Bean之后,Feign在远程调用失败之后会进行重试
     

    FeignService.java

    @Service
    public class FeignService {
    
        @Autowired
        EurekaClientFeign eurekaClientFeign;
    
        public String  port(){
            return eurekaClientFeign.port();
        }
    }
    在Service层FeignService注入EurekaClientFeign去调用port()方法

    FeignController.java

    @RestController
    public class FeignController {
        @Autowired
        FeignService feignService;
    
        @GetMapping("/feign")
        public String sayPort(){
            return  feignService.port();
        }
    }
    自动注入FeignService 去调用其port()方法
    FeignService 通过 EurekaClientFeign远程调用CLIENT服务的API接口“/port”
    此时的两个提供者:

    分别是8089和8090端口
     
    启动服务:

     

    Feign Client 程调用了 eureka-client 务(8089、8090)两个端口的实例“/port”API接口
    Feign Client 有负载均衡的能力。

    spring-cloud-starter-openfeign 的porn 文件

    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter</artifactId>
    </dependency>
    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-openfeign-core</artifactId>
    </dependency>
    <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-web</artifactId>
    </dependency>
    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-commons</artifactId>
    </dependency>
    <dependency>
       <groupId>io.github.openfeign</groupId>
       <artifactId>feign-core</artifactId>
    </dependency>
    <dependency>
       <groupId>io.github.openfeign</groupId>
       <artifactId>feign-slf4j</artifactId>
    </dependency>
    <dependency>
       <groupId>io.github.openfeign</groupId>
       <artifactId>feign-hystrix</artifactId>
    </dependency>
    <dependency>
       <groupId>io.github.openfeign</groupId>
       <artifactId>feign-java8</artifactId>
    </dependency>
    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
       <optional>true</optional>
    </dependency>
    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-netflix-archaius</artifactId>
       <optional>true</optional>
    </dependency>

     5.2、FeignClient详解

     @FeignClient注解源码

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package org.springframework.cloud.openfeign;
    
    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import org.springframework.core.annotation.AliasFor;
    
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface FeignClient {
        @AliasFor("name")
        String value() default "";
    
        /** @deprecated */
        @Deprecated
        String serviceId() default "";
    
        String contextId() default "";
    
        @AliasFor("value")
        String name() default "";
    
        String qualifier() default "";
    
        String url() default "";
    
        boolean decode404() default false;
    
        Class<?>[] configuration() default {};
    
        Class<?> fallback() default void.class;
    
        Class<?> fallbackFactory() default void.class;
    
        String path() default "";
    
        boolean primary() default true;
    }
    FeignClient 注解被@Target(ElementType TYPE)修饰:
    表示 FeignClient 注解的作用目标在接口上
     
    @Retention(RetentionPolicy.RUNTll伍)注解表明该注解会在 lass 字节码文件中存在,
    在运行时可以通过反射获取到
     
    @Documented 表示该注解将被包含在 Javadoc 中。
     
    @Feign Client 注解用于创建声明式 API 接口,该接口是RESTful 风格的。
    Feign 被设计成插拔式的,可以注入其他组件和 Feign一起使用
    最典型的是如果 Ribbon 可用, Feign 会和Ribbon 结合进行负载均衡。
     
    注解中的属性:
    ---value()和 name() 样,是被调用的服务的 Serviceld
    ---url ()直接填写硬编码的Uri 地址
    ---decode404()即 404 是被解码,还是抛异常。
    ---configuration ()指明 FeignClient 配置类,
        默认的配置类为 FeignClientsConfiguration类,在缺省的情况下 这个类注入
        了默认的 DecoderEncoder、 Contract 等配置的 Bean
    ---fall back()为配置熔断器的处理类。

     5.3、FeignClient的配置

    Feign Client 默认的配置类为 FeignClientsConfiguration,这个类在在 pring-cloud-netflix-core的jar下
    现这个类注入了很多 Feign 相关的配置 Bean(默认不配置的时候使用默认的)
    Decoder、Encoder 、Contract个类在没有Bean被注入的情况下,会自动注入默认配置的 Bean

     

    @Configuration
    public class FeignClientsConfiguration {
        @Autowired
        private ObjectFactory<HttpMessageConverters> messageConverters;
        @Autowired(
            required = false
        )
        private List<AnnotatedParameterProcessor> parameterProcessors = new ArrayList();
        @Autowired(
            required = false
        )
        private List<FeignFormatterRegistrar> feignFormatterRegistrars = new ArrayList();
        @Autowired(
            required = false
        )
        private Logger logger;
    
        public FeignClientsConfiguration() {
        }
    
        @Bean
        @ConditionalOnMissingBean
        public Decoder feignDecoder() {
            return new OptionalDecoder(new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
        }
    
        @Bean
        @ConditionalOnMissingBean
        @ConditionalOnMissingClass({"org.springframework.data.domain.Pageable"})
        public Encoder feignEncoder() {
            return new SpringEncoder(this.messageConverters);
        }
    
        @Bean
        @ConditionalOnClass(
            name = {"org.springframework.data.domain.Pageable"}
        )
        @ConditionalOnMissingBean
        public Encoder feignEncoderPageable() {
            return new PageableSpringEncoder(new SpringEncoder(this.messageConverters));
        }
    
        @Bean
        @ConditionalOnMissingBean
        public Contract feignContract(ConversionService feignConversionService) {
            return new SpringMvcContract(this.parameterProcessors, feignConversionService);
        }
    
        @Bean
        public FormattingConversionService feignConversionService() {
            FormattingConversionService conversionService = new DefaultFormattingConversionService();
            Iterator var2 = this.feignFormatterRegistrars.iterator();
    
            while(var2.hasNext()) {
                FeignFormatterRegistrar feignFormatterRegistrar = (FeignFormatterRegistrar)var2.next();
                feignFormatterRegistrar.registerFormatters(conversionService);
            }
    
            return conversionService;
        }
    
        @Bean
        @ConditionalOnMissingBean
        public Retryer feignRetryer() {
            return Retryer.NEVER_RETRY;
        }
    
        @Bean
        @Scope("prototype")
        @ConditionalOnMissingBean
        public Builder feignBuilder(Retryer retryer) {
            return Feign.builder().retryer(retryer);
        }
    
        @Bean
        @ConditionalOnMissingBean({FeignLoggerFactory.class})
        public FeignLoggerFactory feignLoggerFactory() {
            return new DefaultFeignLoggerFactory(this.logger);
        }
    
        @Bean
        @ConditionalOnClass(
            name = {"org.springframework.data.domain.Page"}
        )
        public Module pageJacksonModule() {
            return new PageJacksonModule();
        }
    
        @Configuration
        @ConditionalOnClass({HystrixCommand.class, HystrixFeign.class})
        protected static class HystrixFeignConfiguration {
            protected HystrixFeignConfiguration() {
            }
    
            @Bean
            @Scope("prototype")
            @ConditionalOnMissingBean
            @ConditionalOnProperty(
                name = {"feign.hystrix.enabled"}
            )
            public Builder feignHystrixBuilder() {
                return HystrixFeign.builder();
            }
        }
    }
    重写 FeignClientsConfiguration 类中的 Bean
    覆盖掉默认的配置 Bean 
    从而达到自定义配置的目的
     
    Feign 默认的配置在请求失败后 重试次数为 ,即不重试Retryer.NEVER_RETRY
    现在希望在请求失败后能够重试
    这时需要写 个配置 FeignConfig 类
    在该类中注入Retryer的Bean会覆盖掉默认的 Retryer的Bean
    @Configuration
    public class feignconfig {
        @Bean
        public Retryer feignRetryer(){
            return  new Retryer.Default(100, TimeUnit.SECONDS.toMillis(1L),5);
        }
    }
  • 相关阅读:
    使用svn diff的-r参数的来比较任意两个版本的差异
    mysql client常见error总结
    mysql 中 unix_timestamp,from_unixtime 时间戳函数
    hyperledger explorer 结合 fabric1.4 搭建 区块链浏览器 踩坑记录
    fabric1.4 网络操作
    通过配置连接池大小来提升性能
    docker基本操作及介绍
    InnoDB 引擎中的索引类型
    MySQL互联网业务使用建议
    mysql InnoDB引擎是否支持hash索引
  • 原文地址:https://www.cnblogs.com/Mrchengs/p/10646137.html
Copyright © 2011-2022 走看看