浅析如何使用Spring Cloud OpenFeign

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

一、如何配置 OpenFeign

1、配置 pom.xml
<!-- spring cloud -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

2、主启动类加上 @EnableFeignClients 注解

  @EnableFeignClients 声明该项目是Feign客户端,扫描对应的 feign client。比如我们项目上部分注解

@SpringBootApplication
@EnableScheduling
@EnableFeignClients
@EnableWebMvc
@MapperScan(basePackages = {"com.enmox.emcs.*.dao"})
public class EmcsApplication extends WebMvcConfigurationSupport {
    public static void main(String[] args) {
        SpringApplication.run(EmcsApplication.class, args);
    }
}

3、新增提供者 API 接口

  我们需要集中化管理API,就可以通过接口统一管理,需要新增搜索服务的接口类 SearchService,并添加 @FeignClient(name="searchApi") 注解,其中name就是我们要访问的微服务的名称。其中 POST /search/build?index={index}&id={id} 就是和 searchApi 服务中的路径是一样的。
@FeignClient(name = "searchApi", url = "http://emcs-search:8088")
public interface SearchService {
    //创建索引
    @RequestLine("POST /search/build?index={index}&id={id}")
    @Headers("Content-Type: application/json")
    void build(@Param("index") String index, @Param("id") Integer id);
}

4、在 消费者 Controller 或 Service 里使用

// 注入 service,基础注解自己加咯
private final SearchService searchService;

// 直接使用即可
searchService.build(EmcsType.DBDOC, id);

二、OpenFeign 配置详解

  作为Spring Cloud的子项目之一,Spring Cloud OpenFeign以将OpenFeign集成到Spring Boot应用中的方式,为微服务架构下服务之间的调用提供了解决方案:

  (1)首先,利用了OpenFeign的声明式方式定义Web服务客户端;

  (2)其次还更进一步,通过集成Ribbon或Eureka实现负载均衡的HTTP客户端。

1、OpenFeign 的标注:@FeignClient 和 @EnableFeignClients

  @FeignClient 标注用于声明Feign客户端可访问的Web服务。

  @EnableFeignClients 标注用于修饰Spring Boot应用的入口类,以通知Spring Boot启动应用时,扫描应用中声明的Feign客户端可访问的Web服务。

2、FeignClient 注解的使用介绍

(1)value / name:value和name的作用一样,如果没有配置url,那么配置的值将作为服务名称,用于服务发现;反之只是一个名称。

(2)contextId:比如我们有个user服务,但user服务中有很多个接口,我们不想将所有的调用接口都定义在一个类中,如:

@FeignClient(name = "optimization-user")public interface UserRemoteClient {}

@FeignClient(name = "optimization-user")public interface UserRemoteClient2 {}

  这种情况下启动就会报错了,因为Bean的名称冲突了,具体错误如下:

Description:The bean 'optimization-user.FeignClientSpecification', defined in null, 
could not be registered. A bean with that name has already been defined in
null and overriding is disabled. Action:Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true

  解决方案:

  2.1、可以增加下面的配置,作用是允许出现beanName一样的BeanDefinition

spring.main.allow-bean-definition-overriding=true

  2.2、另一种解决方案就是为每个Client手动指定不同的contextId,这样就不会冲突了。

  上面给出了Bean名称冲突后的解决方案,下面来分析下contextId在Feign Client的作用,在注册Feign Client Configuration的时候需要一个名称,名称是通过getClientName方法获取的,从查看源码里 private String getClientName(Map client) 方法就可以看到如果配置了contextId就会用contextId,如果没有配置就会取value,然后是name,最后是serviceId。默认都没有配置,当出现一个服务有多个Feign Client的时候就会报错了。其次的作用是在注册FeignClient中,contextId会作为Client 别名的一部分,如果配置了qualifier优先用qualifier作为别名。

(3)url:url 用于配置指定服务的地址,相当于直接请求这个服务,不经过Ribbon的服务选择,像调试等场景可以使用。

(4)decode404:当调用请求发生404错误时,decode404的值为true,那么会执行decoder解码,否则抛出异常。

(5)configuration:configuration是配置Feign配置类,在配置类中可以自定义Feign的Encoder、Decoder、LogLevel、Contract等。

(6)path:path定义当前FeignClient访问接口时的统一前缀,比如接口地址是/user/get, 如果你定义了前缀是user, 那么具体方法上的路径就只需要写/get 即可。

三、注解 @EnableFeignClients 工作原理

  详见这篇博客:注解 @EnableFeignClients 工作原理  ——  https://blog.csdn.net/andy_zhang2007/article/details/86680622

原文地址:https://www.cnblogs.com/goloving/p/15062836.html