简介:
feign 是声明式的 web service 客户端,他让微服务之间的调用变得更简单了,类似 controller调用 service。Spring cloud 集成了 Ribbon 和 Eureka ,可以在使用 Feign 时提供负载均衡的 http 客户端
只需要创建一个接口,然后添加注释即可
Feign ,主要是社区,大家都习惯面向接口编程。这个是很多开发人员的规范。
调用微服务访问两种方法:
1、微服务名字 【ribbon】
2、接口和注解 【feign】
Feign能干什么?
Feign 指在使编程 Java Http 变得更容易
前面在使用 Ribbon + RestTemplate 请求的封装处理,形成了一套模版化的调用方法。
但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常会针对每个微服务自行封装一些客户端类来包装这些依赖服务的调用。所以 Feign 在此基础上做了进一步封装,由他来帮助我们定义和实现依赖服务接口的定义。
在 Feign 的实现下,我们只需要创建一个接口并使用注解的方式来配置它(类似于以前 Dao 接口上标注 Mapper 注解,现在是一个微服务接口上面标注一个 Feign注解 即可)即可完成对服务提供方的接口绑定,简化了使用 spring cloud ribbon 时,自动封装服务调用客户端的开发量。
Feign 集成了 Ribbon
利用 Ribbon 维护了 MicroServiceCloud-Dept 的服务列表信息,并通过轮询实现了客户端的负载均衡,而与 Ribbon 不同的是,通过 Feign 只需要定义服务绑定接口且以声明式的方法,优雅且简单的实现了服务调用
为了区别之前的 consume-80 module ,所以创建一个新的 module,
springcloud-consumer-dept-feign,内容、结构都和 consume-80 相同【consume-80在前面 5.0 的文章里有写】
在 springcloud-api【springcloud-api 在4.0文章里有写】 和 springcloud-consumer-dept-feign 都导入以下 feign 的相关依赖:
org.springframework.cloud
spring-cloud-starter-feign
1.4.6.RELEASE
在springcloud-api模块里创建一个service文件夹,在该文件夹下创建一个DeptClientService.java接口文件
package com.hkl.springcloud.service;
import com.hkl.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Repository
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT")
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id") long id);
@GetMapping("/dept/list")
public List queryAll();
@PostMapping("/dept/add")
public Dept addDept(Dept dept);
}
在DeptClientConrtoller中:
package com.hkl.springcloud.controller;
import com.hkl.springcloud.pojo.Dept;
import com.hkl.springcloud.service.DeptClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DeptComsumerController {
//理解:消费者不应该有service层~
//RestTemplate ... 供我们直接调用就可以了 手动注册到Spring中
//(url,参数,返回类型)
@Autowired
private DeptClientService service = null;
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept) {
return service.addDept(dept);
}
@RequestMapping("/consumer/dept/get/{id}")
public Dept queryById(@PathVariable("id") Long id) {
return service.queryById(id);
}
@RequestMapping("/consumer/dept/list")
public List queryAll() {
return service.queryAll();
}
}
最后在主启动类上加上注解 @EnableFeignClients(basePackages = {"com.hkl.springcloud"})
ribbon 整合完 eureka 后:
ribbon 整合完 eureka 后要访问服务,就是在 controller 中通过设置静态变量【静态变量就是http://+服务在eureka中的名称】,然后再通过 RestTemplate 拼接 Provider模块的 RequestMapping 请求来实现访问 provider模块 的 controller层的 RequestMapping 的服务,然后因为 ribbon 要通过服务的名字来实现访问以及负载均衡
feign 整合完 eureka 后:
然后 feign 整合完 eureka 后就是通过在 service层中加上注解@FeignClient(value=服务名称)这样来绑定服务端的接口,然后在 consume模块 的 controller层直接调用 springcloud-api的 service层的接口即可。
区别在于没整合之前访问的接口中带有服务名称并且需要使用 RestTemplate 去调用provider模块的 controller层的RequestMapping,整合之后访问的服务接口中不带有服务名称并且不需要使用 RestTemplate,而是直接调用 springclouds-api 模块的Service层即可,注意这里的service层放的位置是springcloud-api这个模块而不是直接放在provider这个模块,因为如果放在Provider那不就相当于consume直接调用provider了吗?那注册中心还有什么作用呢?