Feign实现服务间的调用(学习笔记)

前言:

Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端。它使得编写Web服务客户端变得更加简单。我们只需要通过创建接口并用注解来配置它既可完成对Web服务接口的绑定。它具备可插拔的注解支持,包括Feign注解、JAX-RS注解。它也支持可插拔的编码器和解码器。Spring Cloud Feign还扩展了对Spring MVC注解的支持,同时还整合了Ribbon和Eureka来提供均衡负载的HTTP客户端实现。

1. 加入Fegin依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2. 在启动类加上@EnableFeignClients注解,开启Feign的功能

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients //加上注解启用fegin功能
public class ClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }
}

3.定义一个feign接口,通过@ FeignClient(“服务名”),来指定调用哪个服务比如在代码中调用了service-test服务的“/hi”接口,代码如下:

@FeignClient("service-test") //注解要指定服务名 _不能有下划线
public interface  FeginHiClient {
    //service-hi服务中名字为"hi"的接口
    @GetMapping("/hi")
    String sayHi();
}

注意事项:

  • 接口上通过注解指定要调用的微服名称(不能有下划线)
  • 接口中写具体的被调用的方法(参考被调用的微服controller类中的方法) 注:记得添加controller类上的路径
  • 调用方通过@Autowired注入接口即可调用
  • 注意启动顺序: 注册中心->被调用的微服->调用方微服

4.在controller层,对外暴露一个"getHi"的API接口,通过上面定义的Feign客户端FeginHiClient来消费服务(调用方通过@Autowired注入接口即可调用)

//编译器报错,无视。 
//因为这个Bean是在程序启动的时候注入的,编译器感知不到,所以报错。
@Autowired
private FeginHiClient feginHiClient;

@GetMapping("/getHi")
    public String hiFromFegin() {
        return feginHiClient.sayHi();
    }

5.启动程序,多次访问http://localhost:8080/getHi,浏览器交替显示

hi!i am come from 8862hi!
i am come from 8863

至此,使用Feign消费服务已实现,Feign内置ribbon,带负载均衡的效果

@feign的name多个相同时候,解决方案:

@feignname存在多个相同时候,启动会报错, 使用场景在于: 一个微服里面有很多个api,但是又不想全部接口定义在同一个调用接口@feign里面!
第一种: 在配置文件上加上配置: spring.main.allow-bean-definition-overriding=true
第二种: @feign注解是使用contextId属性区分;

@FeignClient(contextId = "fooClient", name = "stores")
public interface FooClient {
    //..
}
---------------------------------------------------------
@FeignClient(contextId = "BarClient", name = "stores")
public interface BarClient {
    //..
}

扩展:带参数的feign接口写法:

注意 : 有参数一定要有注解并指定参数名称,否则出错

@FeignClient("EUREKA-TEST")
public interface TestService {

    @GetMapping("/findOneMap")
    Map<String, Object> findOneMap(@RequestParam("id") String id);

}

--------------------------------restful风格 ↓--------------------------------
  
@FeignClient("tensquare-base")
public interface LabelClient {

    @RequestMapping(value="/label/{id}", method = RequestMethod.GET)
    public Result findById(@PathVariable("id") String id);
}

----------------------------传递json实体参数使用 @RequestBody ↓----------------------
@RequestMapping(value = "/add",method = RequestMethod.POST)
String add(@RequestBody User user);

Feign的优势(相比RestTemplate)

1.声明式的REST客户端,通过编写简单的接口和插入注解,只需要像调用本地方法一样调用它就可以完成服务请求及相关处理,使REST调用更加简单

若使用RestTemplate,则需要深入了解HTTP级别API的细节。

客户端,通过编写简单的接口和插入注解,只需要像调用本地方法一样调用它就可以完成服务请求及相关处理,使REST调用更加简单

若使用RestTemplate,则需要深入了解HTTP级别API的细节。

2.内置Ribbon,配合Eureka实现负载均衡