zoukankan      html  css  js  c++  java
  • Spring Cloud(Dalston.SR5)--Feign 声明式REST客户端

    Spring Cloud 对 Feign 进行了封装,集成了 Ribbon 并结合 Eureka 可以实现客户端的负载均衡,Spring Cloud 实现的 Feign 客户端类名为 LoadBalancerFeignClient,在该类中,维护着与 SpringClientFactory 相关的实例,通过SpringClientFactory 可以获取负载均衡器,负载均衡器会根据一定的规则来选取处理请求的服务器,最终实现负载均衡功能。

    集成了 Hystrix 增加了服务容错处理,并为 Feign 的使用提供了各种默认属性,例如编码器、解码器、日志、注解翻译器、实例创建者和客户端,我们可以简单的使用 Feign,也可以增加自定义的配置,下面我们在 Spring Cloud 中使用 Feign 示例如下:

    • 创建项目

      创建名称为 spring-cloud-feign-client 的 Spring Cloud 项目,修改 POM.xml 中增加以下依赖项:

      <?xmlversion="1.0"encoding="UTF-8"?>

      <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">

      <modelVersion>4.0.0</modelVersion>

         

      <groupId>org.lixue</groupId>

      <artifactId>spring-cloud-feign-client</artifactId>

      <version>0.0.1-SNAPSHOT</version>

      <packaging>jar</packaging>

         

      <name>spring-cloud-feign-client</name>

      <description>DemoprojectforSpringBoot</description>

         

      <parent>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-parent</artifactId>

      <version>1.5.4.RELEASE</version>

      <relativePath/><!--lookupparentfromrepository-->

      </parent>

         

      <properties>

      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

      <java.version>1.8</java.version>

      <spring-cloud.version>Dalston.SR5</spring-cloud.version>

      </properties>

         

      <dependencies>

      <dependency>

      <groupId>org.springframework.cloud</groupId>

      <artifactId>spring-cloud-starter-eureka</artifactId>

      </dependency>

      <dependency>

      <groupId>org.springframework.cloud</groupId>

      <artifactId>spring-cloud-starter-feign</artifactId>

      </dependency>

      <dependency>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-test</artifactId>

      <scope>test</scope>

      </dependency>

      </dependencies>

      <dependencyManagement>

      <dependencies>

      <dependency>

      <groupId>org.springframework.cloud</groupId>

      <artifactId>spring-cloud-dependencies</artifactId>

      <version>${spring-cloud.version}</version>

      <type>pom</type>

      <scope>import</scope>

      </dependency>

      </dependencies>

      </dependencyManagement>

      <build>

      <plugins>

      <plugin>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-maven-plugin</artifactId>

      </plugin>

      </plugins>

      </build>

      </project>

         

    • 创建 Feign 接口

      在 Spring Cloud 中使用 Feign ,需要使用的是 Spring Cloud 的相关注解,例如 @RequestMapping、@RequestParam 等,而不是 Feign 的注解,创建 HelloWorldClient 接口,使用 @FeignClient 注解来标注服务名称(调用服务的 spring.application.name 属性),使用 @RequestMapping 来标注 REST 服务的相关属性;@RequestParam 和 @PathVariable 注解标注请求参数

      package org.lixue;

         

      import org.springframework.cloud.netflix.feign.FeignClient;

      import org.springframework.http.MediaType;

      import org.springframework.web.bind.annotation.PathVariable;

      import org.springframework.web.bind.annotation.RequestMapping;

      import org.springframework.web.bind.annotation.RequestMethod;

      import org.springframework.web.bind.annotation.RequestParam;

         

      @FeignClient("helloworld-provider")

      public interface HelloWorldClient{

      @RequestMapping(path="/speak?body={body}",method=RequestMethod.GET)

      String speak(@RequestParam(value="body",required=false) String body);

         

      @RequestMapping(path="/person/{personId}",method=RequestMethod.GET,

      produces=MediaType.APPLICATION_JSON_UTF8_VALUE)

      Person findById(@PathVariable("personId")Integer personId);

         

      @RequestMapping(path="/person/create",method=RequestMethod.POST,

      consumes=MediaType.APPLICATION_JSON_UTF8_VALUE,

      produces=MediaType.APPLICATION_JSON_UTF8_VALUE)

      ReturnValue create(Person person);

      }

         

    • 启动类启用 Feign

      Feign 集成了 Ribbon 并结合 Eureka 可以实现客户端的负载均衡,因此在启动类我们需要启动 Eureka客户端和 Feign,使用 @EnableEurekaClient 启用 Eureka 客户端;使用 @EnableFeignClients 启用 Feign

      package org.lixue;

         

      import org.springframework.boot.SpringApplication;

      import org.springframework.boot.autoconfigure.SpringBootApplication;

      import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

      import org.springframework.cloud.netflix.feign.EnableFeignClients;

         

      @SpringBootApplication

      @EnableEurekaClient

      @EnableFeignClients

      public class SpringCloudFeignClientApplication{

      public static void main(String[]args){

      SpringApplication.run(SpringCloudFeignClientApplication.class,args);

      }

      }

         

    • 增加配置

      Feign 集成了 Ribbon 并结合 Eureka 可以实现客户端的负载均衡,因此需要增加 Eureka 相关配置,指定 eureka 服务注册中心的地址

      ##配置应用名称

      spring:

      application:

      name:spring-cloud-feign-client

      #配置服务端口

      server:

      port:8070

      #设置eureka服务注册中心的地址,如果多个以逗号分割

      eureka:

      client:

      service-url:

      defaultZone:http://eurekaserver01:9000/eureka/,http://eurekaserver02:9000/eureka/

         

    • 创建 REST 服务

      在调用服务时,只需要使用 @Autowired 注解标注 Feign 接口 HelloWorldClient , Spring Cloud 会帮我们创建和维护客户端实例

      package org.lixue;

         

      import org.springframework.beans.factory.annotation.Autowired;

      import org.springframework.http.MediaType;

      import org.springframework.web.bind.annotation.*;

         

      @RestController

      public class InvokerController{

         

      @Autowired

      private HelloWorldClient helloWorldClient;

         

      @RequestMapping(path="/invokerSpeak",method=RequestMethod.GET)

      public String invokerSpeak(@RequestParam(name="body",required=false)String body){

      return helloWorldClient.speak(body);

      }

         

      @RequestMapping(path="/invokerFindByID/{personID}",method=RequestMethod.GET,

      produces=MediaType.APPLICATION_JSON_UTF8_VALUE)

      public Person invokerFindByID(@PathVariable("personID")Integer personID){

      return helloWorldClient.findById(personID);

      }

         

      @RequestMapping(path="/invokerCreate",method=RequestMethod.GET,

      produces=MediaType.APPLICATION_JSON_UTF8_VALUE)

      ReturnValue invokerCreate(){

      Person newPerson=new Person();

      newPerson.setId(3434);

      newPerson.setAge(34);

      newPerson.setName("343434");

      newPerson.setMessage("33333333333333333");

      return helloWorldClient.create(newPerson);

      }

      }

         

    • 测试验证

      启动 eureka-server 和 service-provider 项目,启动该项目后,访问地址 http://localhost:8070/invokerSpeak 可以查看到访问,如果启动了多个 service-provider ,多次刷新可以看到,具体的服务调用被轮询调用。

    日志配置

    启用服务的 Feign 日志,增加配置 Bean 如下:

    package org.lixue;

       

    import feign.Logger;

    import org.springframework.context.annotation.Bean;

       

    public class MyFeignConfiguration{

    @Bean

    publicLogger.Level level(){

    returnLogger.Level.FULL;

    }

    }

    在 Feign 接口的 @FeignClient 注解中,增加 configuration 指向到创建的配置类:

    @FeignClient(value="helloworld-provider",configuration=MyFeignConfiguration.class)

    public interface HelloWorldClient{

    //其他代码如上

    }

    修改 src/main/resources 目录下的 application.yml 增加日志级别配置:

    logging:

    level:

    org.lixue.HelloWorldClient: debug

       

    此时就可以看到请求日志的输出,如下:

    2018-04-06 12:43:24.578 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] ---> GET http://helloworld-provider/speak HTTP/1.1

    2018-04-06 12:43:24.581 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] ---> END HTTP (0-byte body)

    2018-04-06 12:43:25.112 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] <--- HTTP/1.1 200 (529ms)

    2018-04-06 12:43:25.112 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] content-length: 21

    2018-04-06 12:43:25.113 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] content-type: text/plain;charset=UTF-8

    2018-04-06 12:43:25.113 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] date: Fri, 06 Apr 2018 04:43:25 GMT

    2018-04-06 12:43:25.113 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] x-application-context: helloworld-provider:8001

    2018-04-06 12:43:25.113 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak]

    2018-04-06 12:43:25.118 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] hello world port:8001

    2018-04-06 12:43:25.118 DEBUG 3968 --- [nio-8070-exec-4] org.lixue.HelloWorldClient : [HelloWorldClient#speak] <--- END HTTP (21-byte body)

       

    默认配置

    Spring Cloud 为 Feign 的使用提供了各种默认属性,默认情况下,Spring 将会为 Feign 的属性提供以下 Bean 来实现 Feign 的调用

    Bean 类型

    Bean 名称

    实现类

    说明

    Decoder

    feignDecoder

    ResponseEntityDecoder

    解码器

    Encoder

    feignEncoder

    SpringEncoder

    编码器

    Logger

    feignLogger

    Slf4jLogger

    日志

    Contract

    feignContract

    SpringMvcContract

    注解翻译器

    Feign.Builder

    feignBuilder

    HystrixFeign.Builder

    Feign 实例创建者

    Client

    feignClient

      

    Feign 客户端,启用 Ribbon 实现类为LoadBalancerFeignClient 否则为 Feign 默认实现类

    Logger.Level

    自命名

    没有默认提供,只需要提供该类型的 Bean 即可

    Retryer

    自命名

    没有默认提供,只需要提供该类型的 Bean 即可

    ErrorDecoder

    自命名

    没有默认提供,只需要提供该类型的 Bean 即可

    Request.Options

    自命名

    没有默认提供,只需要提供该类型的 Bean 即可

    RequestInterceptor

    自命名

    没有默认提供,只需要提供该类型的 Bean 即可

       

  • 相关阅读:
    python 内存泄漏——使用pymssql模块的讨论 free(): corrupted unsorted chunks
    Python的gc模块
    使用多线程——线程池
    sqlserver 数据库连接池
    drf response——简单封装
    邮箱找回密码实现
    阿里云 oss 服务 —— 上传图片,获取url
    dajngo-apscheduler 实现定时任务
    kubernetes基础概念
    Path must be a string.
  • 原文地址:https://www.cnblogs.com/li3807/p/8916783.html
Copyright © 2011-2022 走看看