SpringCloud微服务之四:Feign实现声明式REST调用(一)


文章目录

  • SpringCloud微服务之四:Feign实现声明式REST调用(一)
  • 前言
  • 一、Feign简介
  • 二、服务消费者整合Feign
  • 1.添加依赖
  • 2.创建Feign接口
  • 3.启动类上添加启动功能注解
  • 4、调用测试
  • 三、自定义Feign配置
  • 1.Feign自带的一些注解
  • 2.Feign自定义拦截器
  • 3、使用属性自定义Feign配置


前言

Spring Cloud OpenFeign 是声明式的服务调用工具,它整合了Ribbon和Hystrix,拥有负载均衡和服务容错功能,本文将对其用法进行详细介绍。

一、Feign简介

Feign是Netflix开发的声明式的服务调用工具,我们只需创建一个接口并用注解的方式来配置它,就可以实现对某个服务接口的调用,简化了直接使用RestTemplate来调用服务接口的开发量。Feign具备可插拔的注解支持,同时支持Feign注解、JAX-RS注解及SpringMvc注解。当使用Feign时,Spring Cloud集成了Ribbon和Eureka以提供负载均衡的服务调用及基于Hystrix的服务容错保护功能。

二、服务消费者整合Feign

1.添加依赖

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <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-openfeign</artifactId>
    </dependency>

2.创建Feign接口

package com.yangxf.cloud.study.user.feign;

import com.yangxf.cloud.study.user.entity.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(name = "microservice-provider-user")
public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
}

3.启动类上添加启动功能注解

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class ConsumerMovieApplication {
  public static void main(String[] args) {
    SpringApplication.run(ConsumerMovieApplication.class, args);
  }
}
  • 这是使用啦Eureka注册表,microservice-provider-user是已经注册的服务名,如不想使用Eureka,
  • 也可以通过microservice-provider-user.ribbon.listOfServers属性配置服务集合,逗号分隔,如microservice-provider-user.ribbon.listOfServers=localhost:8000,localhost:8001完成服务地址配置;
  • 也可以通过@FeignClient(name = “microservice-provider-user”,url=“http://localhost:8000/”)注解配置

4、调用测试

package com.yangxf.cloud.study.user.controller;

import com.yangxf.cloud.study.user.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.yangxf.cloud.study.user.feign.UserFeignClient;

@RestController
public class MovieController {
  @Autowired
  private UserFeignClient userFeignClient;

  @GetMapping("/user/{id}")
  public User findById(@PathVariable Long id) {
    return this.userFeignClient.findById(id);
  }
}

多次访问http://localhost:8010/user/1,可以看到多个microservice-provider-user的控制台都有日志数据;

总结:使用Feign不但实现了声明式的REST API的调用,同时实现了客户端侧的负载均衡。

三、自定义Feign配置

  • 很多场景下,我们需要自定义Feign的配置,例如配置,日志级别、定义拦截器等。
  • Spring Cloud Edgware版本后允许通过java代码和属性配置。
  • Spring Cloud中,默认配置类是FeignClientsConfiguration,该类定义了Feign的默认使用的编码器,解码器,所使用的契约等信息;
  • Spring Cloud允许通过@FeignClient中configuration属性自定义Feign的配置,优先级高于默认配置类,自定义的配置类不要放在启动项扫描范围之内。

1.Feign自带的一些注解

// 1、正常使用、正常书写
    @Headers({"Accept:*/*", "Accept-Language:    zh-cn"})
    @RequestLine("GET /feign/demo1?name={name}")
    String testRequestLine(@Param("name") String name);

    // 2、GET后不止一个空格,有多个空格
    @RequestLine("GET             /feign/demo1?name={name}")
    String testRequestLine2(@Param("name") String name);

    // 3、使用Map一次性传递多个查询参数,使用注解为@QueryMap
    @RequestLine("GET /feign/demo1")
    String testRequestLine3(@QueryMap Map<String, Object> params);

    // 4、方法参数上不使用任何注解
    @RequestLine("GET /feign/demo1")
    String testRequestLine4(String name);

    // 5、方法上标注有@Body注解,然后把方法参数传递给它
    @RequestLine("GET /feign/demo1")
    @Body("{name}")
    String testRequestLine5(@Param("name") String name);

2.Feign自定义拦截器

比如,一些一些借口需要进行基于HTTP BASIC的认证后才能调用,配置如下:

package com.yangxf.cloud.config;

import feign.auth.BasicAuthRequestInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import feign.Contract;

/**
 * 该类为Feign的配置类
 * 注意:该不应该在主应用程序上下文的@ComponentScan中。
 * @author linwd
 */
@Configuration
public class FeignConfiguration {
  /**
   * 将契约改为feign原生的默认契约。这样就可以使用feign自带的注解了。
   * @return 默认的feign契约
   */
  @Bean
  public Contract feignContract() {
    return new feign.Contract.Default();
  }

  @Bean
  public BasicAuthRequestInterceptor basicAuthRequestInterceptor(){
    return new BasicAuthRequestInterceptor("user","password1");
  }
}

3、使用属性自定义Feign配置

属性配置优先级高于java配置

feign:
  client:
    config:
      default: #默认全局配置
        conectTimeOut: 5000 #相当于Request.Options
        readTimeOut: 5000 #相当于Request.Options
        loggerLevel: basic
      oneFeignName: #feign服务名
        conectTimeOut: 5000 #相当于Request.Options
        readTimeOut: 5000 #相当于Request.Options
        loggerLevel: full #配置日志级别,相当于代码配置中Logger
        errorDecoder: com.yangxf.SimpleErrorDecoder #错误解码器,相当于代码中ErrorDecoder
        retryer: com.yangxf.SimpleRetryer #配置重试,相当于代码中Retryer
        requestInterceptors:  #拦截器
          - com.yangxf.OneRequestInterceptor
          - com.yangxf.TwoRequestInterceptor
        decode404: false