精华内容
参与话题
问答
  • OpenFeign

    千次阅读 2018-03-16 16:29:59
    Feign Fiegn包含以下组件 Contract:Defines what annotations and values are valid on interfaces. ...RequestTemplate对象用来Build一个Request对象,传递给Client对象,Client执行请求之前,可以...

    Feign

    Fiegn包含以下组件
    Contract:Defines what annotations and values are valid on interfaces.
    Client:具体执行HTTP请求的地方,传入Request对象,获得Response对象;RequestTemplate对象用来Build一个Request对象,传递给Client对象,Client执行请求之前,可以被RequestInterceptor处理,得到Response请求之后可以被ResponseMapper处理;
    Retryer
    Logger
    Encoder
    Decoder
    ErrorDecoder
    Target:就是要处理的接口类,有两个实现EmptyTarget和HardCodedTarget
    RequestTemplate:每个方法在每次调用时都会先生成这个对象,生成这个对象的信息来自每个方法对应的MethodMetadata对象;

    代理模块

    ReflectiveFeign和SynchronousMethodHandler
    InvocationHandler:Feign启动时,给一个Target创建一个FeignInvocationHandler对象,此类有个工厂类InvocationHandlerFactory;
    Fiegn启动过程:
    1.Feign.build()的时候,其实是生成了一个ReflectiveFeign对象;
    2.接着调用public T newInstance(Target target),处理这个Target,处理过程如下
    3.遍历这个Target的所有方法,为每一个方法生成一个SynchronousMethodHandler对象,将方法签名和辞方法的SynchronousMethodHandler对应关系存储到Map对象中;
    4.InvocationHandlerFactory传入辞Target和上面的Map,生成一个InvocationHandler对象;这个对象的具体实现是ReflectiveFeign.FeignInvocationHandler;
    5.用上面生成的ReflectiveFeign.FeignInvocationHandler对象,为当前处理的Target生成一个代理;
    FiegnTarget方法调用处理流程
    1.前面提到Feign启动时会为每一个Target生成一个代理对象,这个代理对象的InvocationHandler是ReflectiveFeign.FeignInvocationHandler;
    2.当调用Target的某个方法时,会进入到ReflectiveFeign.FeignInvocationHandler的invoke方法;
    3.这个方法的主要逻辑就是根据根据当前调用的Method,从存储方法签名和辞方法的SynchronousMethodHandler对应关系到Map对象中,取出SynchronousMethodHandler对象,然后调用SynchronousMethodHandler对象的invoke方法
    4.SynchronousMethodHandler对象中持有当前调用的方法的MethodMetadata,当前的Target对象,发起Http请求的Client对象,Retryer….等等,在SynchronousMethodHandler对象的invoke方法中会直接发起请求,并处理请求响应;
    5.SynchronousMethodHandler的invoke方法返回的结果,就是调用Target的业务方法的结果;

    Annotation

    @RequestLine
    @Headers
    @HeaderMap
    @Body
    @Param
    @QueryMap

    Feign & Ribbon

    Feign 提供了一个feign-ribbon模块用来使用Ribbon的客户端负载均衡能力;

    ConfigurationManager.loadPropertiesFromResources("sample-client.properties");
    GitHubService service = Feign.builder().client(RibbonClient.create()).decoder(new GsonDecoder())
            .target(LoadBalancingTarget.create(GitHubService.class, GitHubService.URL));
    List<Contributor> contributors = service.contributors("OpenFeign", "feign");
    for (Contributor contributor : contributors) {
        System.out.println(contributor.getLogin() + " (" + contributor.getContributions() + ")");
    }
    ConfigurationManager.loadPropertiesFromResources("sample-client.properties");
    GitHubService service = Feign.builder().client(RibbonClient.create()).decoder(new GsonDecoder())
            .target(GitHubService.class, GitHubService.URL);
    List<Contributor> contributors = service.contributors("OpenFeign", "feign");
    for (Contributor contributor : contributors) {
        System.out.println(contributor.getLogin() + " (" + contributor.getContributions() + ")");
    }

    Spring Cloud Feign

    FeignContext:A factory that creates instances of feign classes. It creates a Spring ApplicationContext per client name, and extracts the beans that it needs from there.
    @FeignClient中可以配置一个configuration类,功能就是依赖上边的能力实现的,为每个FiegnClient创建一个子IOC容器;默认的配置是FeignClientsConfiguration类;
    SpringMvcContract:我们在FeignClient的方法上写RequestMapping之所以生效,就是因为这个类;
    @PathVariable/@RequestHeader/@RequestParam的处理逻辑是PathVariableParameterProcessor/RequestHeaderParameterProcessor/RequestParamParameterProcessor实现的,这三个类最终会在SpringMvcContract被调用处理对应的注解;

    Spring Cloud Netflix Feign & Spring Cloud Netflix Ribbon

    Spring Cloud Netflix Feign是模仿feign-ribbon模块的模式,重新实现了一遍接口;
    LoadBalancerFeignClient:Spring Cloud Netflix Feign 实现了Feign的Client接口;LoadBalancerFeignClient的execute方法使用的是FeignLoadBalancer接口的executeWithLoadBalancer方法请求的接口;
    FeignLoadBalancer:AbstractLoadBalancingClient的实现,真正发生HTTP 请求的地方;

    参考

    retrofit
    feign
    spring-cloud-openfeign
    SpringCloud之Feign(一)
    SpringCloud之Feign(二)
    深入理解Feign之源码解析
    spring环境中Feign + Ribbon的使用

    展开全文
  • OPenFeign

    2020-10-03 22:51:35
    OPenFeign Feign是一个声明式的WebService客户端, 使用Feign能让编写Web Service客户端更加简单 它使用的方法是定义个服务接口然后在上面添加注解,Feign也支持可插拔式的编码器和解码器,SpringCloud对feign进行了...

    OPenFeign

    Feign是一个声明式的WebService客户端, 使用Feign能让编写Web Service客户端更加简单

    它使用的方法是定义个服务接口然后在上面添加注解,Feign也支持可插拔式的编码器和解码器,SpringCloud对feign进行了封装支持SpringMVC中标准注解和httpMessageConverteres。Feign还可以与EUREKA和Ribbon组合使用支持负载均衡

    能干嘛

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GSbZR5YH-1601736701617)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200818161424095.png)]

    Feign 和 OPenFeign的区别

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qf3WCKZt-1601736701622)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200818162227529.png)]

    使用步骤(总的来说: 微服务调用接口+@FeignClient)

    自带负载均衡的配置项

    1.建Model cloud-consumer-feign-order80 消费端使用

    2.写pom

    
        <dependencies>
            <!--openfeign-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <!--eureka client-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
            <dependency>
                <groupId>com.atguigu.springcloud</groupId>
                <artifactId>cloud-api-common</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--监控-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <!--热部署-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    

    3.改yml

    server:
      port: 80 # 模拟不用加端口
    spring:
      application:
        name: cloud-order-service
    
    
    eureka:
      client:  # false 表示不向注册中心注册自己
        register-with-eureka: true   # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
        fetch-registry: true
        service-url:
          # 设置与Eureka Server 交互的地址查询服务和注册服务都需要依赖这个地址
          # defaultZone: http://localhost:7001/eureka/  单机版
          defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
    
    # 设置feign客户端超时时间(OpenFeign默认支持ribbon)
    ribbon:
      # 指的是建立连接所用的时间,适用于网络状态正常的情况下,两端连接所用的时间
      ReadTimeout: 5000
      # 指的是建立连接后从服务器读取到可用资源所用的时间
      ConnectTimeout: 5000
    logging:
      level:
        # feign 日志以及什么级别监控哪个接口
       com.atguigu.springcloud.service.PaymentFeignService: debug
    
    

    4.改启动类

    @SpringBootApplication
    @EnableEurekaClient
    @EnableFeignClients
    public class OrderFeignMain80 {
        public static void main(String[] args) {
            SpringApplication.run(OrderFeignMain80.class, args);
        }
    }
    

    5.业务类

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J0W9GNKf-1601736701623)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200818170826105.png)]

    调用其他提供服务的模块

    @Component
    @FeignClient(value = "CLOUD-PAYMENT-SERVICE")
    public interface PaymentFeignService {
    
        @GetMapping(value="/payment/get/{id}")
        public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
    
        @GetMapping("/payment/feign/timeout")
        public String paymentFeignTimeout();
    
    }
    
    

    6.控制层

    @RestController
    @Slf4j
    public class OrderFeignController {
    
        @Resource
        private PaymentFeignService paymentFeignService;
    
        @GetMapping(value = "/consumer/payment/get/{id}")
        public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
            return paymentFeignService.getPaymentById(id);
        }
        @GetMapping("/consumer/payment/feign/timeout")
        public String paymentFeignTimeout() {
            //openfeign-ribbon 客户端默认等待1s
            return paymentFeignService.paymentFeignTimeout();
        }
    
    }
    

    小总结

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XF7tVcuK-1601736701626)(C:\Users\74551\AppData\Roaming\Typora\typora-user-images\image-20200818171040614.png)]

    超时设置 OPenFeign 默认等待1秒钟 超过后会报错

    # 设置feign客户端超时时间(OpenFeign默认支持ribbon)
    ribbon:
      # 指的是建立连接所用的时间,适用于网络状态正常的情况下,两端连接所用的时间
      ReadTimeout: 5000
      # 指的是建立连接后从服务器读取到可用资源所用的时间
      ConnectTimeout: 5000
    

    日志打印功能

    1.配置Bean

    @Configuration
    public class FeignConfig {
    
        /**
         * feignClient配置日志级别
         *
         * @return
         */
        @Bean
        public Logger.Level feignLoggerLevel() {
            // 请求和响应的头信息,请求和响应的正文及元数据
            return Logger.Level.FULL;
        }
    }
    

    2.yml增加配置

    logging:
      level:
        # feign日志以什么级别监控哪个接口
        com.atguigu.springcloud.service.PaymentFeignService: debug
     
    
    展开全文
  • 环境: maven3.0+springboot2.2.0 ...如果不添加spring-cloud-openfeign-core,注解无法使用。 如果添加了他,启动项目时报错context找不到。 真心是无解了。。。。这springboot2.2.0怎么这么多坑
  • 因为现在需要使用get方式传递对象参数,所以尝试在openfeign里面配置httpclient。 配置代码如下: 在yml文件里面增加了配置信息 ``` feign: httpclient: enabled: true ``` 在pom.xml文件中引入的依赖:...
  • Moving to openfeign is the right move for them too, though, as this is the future groupname for this set of packages and the old name is no longer updated. - Could see issues from the large version ...
  • OpenFeign 简介

    千次阅读 2019-03-22 01:07:55
    简介 Feign是一个声明式的Web Service客户端。它的出现使开发Web Service客户端变得很简单。使用Feign只需要创建一个接口加上对应的注解,比如:FeignClient注解。Feign有可插拔的注解,包括Feign注解和JAX-RS注解。...

    简介

    Feign是一个声明式的Web Service客户端。它的出现使开发Web Service客户端变得很简单。使用Feign只需要创建一个接口加上对应的注解,比如:FeignClient注解。Feign有可插拔的注解,包括Feign注解和JAX-RS注解。Feign也支持编码器和解码器,Spring Cloud Open Feign对Feign进行增强支持Spring MVC注解,可以像Spring Web一样使用HttpMessageConverters等。

    Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign,可以做到使用HTTP请求访问远程服务,就像调用本地方法一样的,开发者完全感知不到这是在调用远程方法,更感知不到在访问HTTP请求。

    功能

    1. 可插拔的注解支持,包括Feign注解和JAX-RS注解。
    2. 支持可插拔的HTTP编码器和解码器(Gson,Jackson,Sax,JAXB,JAX-RS,SOAP)。
    3. 支持Hystrix和它的Fallback。
    4. 支持Ribbon的负载均衡。
    5. 支持HTTP请求和响应的压缩。
    6. 灵活的配置:基于 name 粒度进行配置
    7. 支持多种客户端:JDK URLConnection、apache httpclient、okhttp,ribbon)
    8. 支持日志
    9. 支持错误重试
    10. url支持占位符
    11. 可以不依赖注册中心独立运行

    示例

    import com.google.gson.Gson;
    import com.google.gson.JsonIOException;
    import java.io.IOException;
    import java.io.Reader;
    import java.lang.reflect.Type;
    import java.util.List;
    import feign.Feign;
    import feign.Logger;
    import feign.Param;
    import feign.RequestLine;
    import feign.Response;
    import feign.codec.Decoder;
    import static feign.Util.ensureClosed;
    
    /**
     * adapted from {@code com.example.retrofit.GitHubClient}
     */
    public class GitHubExample { 
      public static void main(String... args) {
        GitHub github = Feign.builder()
            .decoder(new GsonDecoder())
            .logger(new Logger.ErrorLogger())
            .logLevel(Logger.Level.BASIC)
            .target(GitHub.class, "https://api.github.com");
    
        System.out.println("Let's fetch and print a list of the contributors to this library.");
        List<Contributor> contributors = github.contributors("netflix", "feign");
        for (Contributor contributor : contributors) {
          System.out.println(contributor.login + " (" + contributor.contributions + ")");
        }
      }
    
      interface GitHub {
    
        @RequestLine("GET /repos/{owner}/{repo}/contributors")
        List<Contributor> contributors(@Param("owner") String owner, @Param("repo") String repo);
      }
    
      static class Contributor {
    
        String login;
        int contributions;
      }
    
      /**
       * Here's how it looks to write a decoder. Note: you can instead use {@code feign-gson}!
       */
      static class GsonDecoder implements Decoder {
    
        private final Gson gson = new Gson();
    
        @Override
        public Object decode(Response response, Type type) throws IOException {
          if (void.class == type || response.body() == null) {
            return null;
          }
          Reader reader = response.body().asReader();
          try {
            return gson.fromJson(reader, type);
          } catch (JsonIOException e) {
            if (e.getCause() != null && e.getCause() instanceof IOException) {
              throw IOException.class.cast(e.getCause());
            }
            throw e;
          } finally {
            ensureClosed(reader);
          }
        }
      }
    

    最后

    作为一款全功能的 Http 客户端,Feign 非常好用。此外,仅仅不到 2 万行的代码,非常适合新手进行源码剖析的入门款。

    展开全文
  • OpenFeign

    2020-06-17 17:30:49
    cloud组件之(OpenFeign坑) opengin使用步骤: 接口+注解(@FeignClient) 主启动类加上@EnableFeignClients 找错1半小时才找到!!!!!! 错误写法: @Component @FeignClient(value = "CLOUD-PAYMENT-SERVICE")...

    cloud组件之(OpenFeign坑)

    opengin使用步骤:
    接口+注解(@FeignClient)
    主启动类加上@EnableFeignClients

    找错1半小时才找到!!!!!!
    错误写法:

    @Component
    @FeignClient(value = "CLOUD-PAYMENT-SERVICE")
    public interface OrderService {
        @GetMapping(value = "/getpaymentById/{id}")
        Map getpaymentById(@PathVariable Integer id);
    }
    
    

    会报错:
    2020-06-17 17:17:44.754 WARN 5948 — [ restartedMain] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘orderController’: Unsatisfied dependency expressed through field ‘orderService’; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘com.zsp.springcloud.service.OrderService’: FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: PathVariable annotation was empty on param 0.
    报错原因:

    @PathVariable Integer id 错误写法导致报错
    @PathVariable(“id”) Integer id 正确写法

    正确写法:

    @Component
    @FeignClient(value = "CLOUD-PAYMENT-SERVICE")
    public interface OrderService {
        @GetMapping(value = "/getpaymentById/{id}")
        Map getpaymentById(@PathVariable("id") Integer id);
    }
    
    
    展开全文

空空如也

1 2 3 4 5 ... 20
收藏数 4,183
精华内容 1,673
关键字:

openfeign