1.簡介
feign是聲明式的web service客戶端,它讓微服務之間的調用變得更簡單了,類似controller調用service,Spring Cloud集成了Ribbon和Eureka,可在使用Feign時提供負載均衡的http客戶端
2.Feign的作用
-
Feign旨在使編寫Java Http客戶端變得更容易
-
前面在使用Ribbon+RestTemplate時,利用RestTemplate對Http請求的封裝處理,形成一套模板化的調用方法。但是在實際開發中,由於對服務依賴的調用可能不止一處,往往一個接口會被多處調用,所以通常都會針對每個微服務自行封裝一些客戶端類來包裝這些依賴服務的調用。所以,Feign在此基礎上做了進一步封裝,由他來幫我們定義和實現依賴服務接口的定義,在Feign的實現下,我們只需要創建一個接口並使用注解的方式來配置它(類似於以前Dao接口上標注Mapper注解,現在是一個微服務接口上面標注一個Feign注解即可)即可完成對服務提供方的接口綁定,簡化了使用Spring Cloud Ribbon時,自動封裝服務調用客戶端的開發量
3.Feign集成了Ribbon
利用Ribbon維護了MicroServiceCloud-Dept的服務列表,並且通過了輪詢實現了客戶端的負載均衡,而與Ribbon不同的是,通過Feign只需要定義服務綁定接口且以聲明式的方法,優雅而且簡單的實現了服務調用
4.Feign實戰
前提:在上一篇文章負載均衡及Ribbon中的Rbbon實戰項目的基礎上進行改動
4.1對springcloud-api項目做出的修改
- 添加feign的依賴
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
- 在com.zixin.springcloud包下創建service文件夾,並在該文件夾中創建FeignDeptService接口
package com.zixin.springcloud.service;
import com.zixin.springcloud.pojo.Dept;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Component
@FeignClient(value = "PROVIDER-DEPT/provider/dept")
public interface FeignDeptService {
//添加部門
@PostMapping("/addDept")
int addDept(Dept dept);
//根據id查詢部門信息
@GetMapping("/findDeptById/{deptno}")
Dept findDeptById(Long deptno);
//查詢所有部門信息
@GetMapping("/findDeptList")
List<Dept> getDeptList();
}
4.2對consumer-dept-9001項目進行修改
-
新建consumer-dept-9002項目,並把consumer-dept-9001項目的代碼復制過來
-
在原來依賴的基礎上添加feign的依賴,全部依賴如下:
<dependencies>
<dependency>
<groupId>com.zixin.springcloud</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-ribbon -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
</dependencies>
- 修改ConsumerController 中調用接口的方式
package com.zixin.springcloud.controller;
import com.zixin.springcloud.pojo.Dept;
import com.zixin.springcloud.service.FeignDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class ConsumerController {
//引入FeignDeptService
@Autowired
private FeignDeptService feignDeptService = null;
@RequestMapping("/consumer/dept/addDept")
public String addDept(@RequestBody Dept dept){
int i = feignDeptService.addDept(dept);
if(i > 0){
return "添加部門信息成功~";
}else{
return "添加部門信息失敗~";
}
}
@RequestMapping("/consumer/dept/findDeptById/{deptno}")
public Dept findDeptById(@PathVariable Long deptno){
return feignDeptService.findDeptById(deptno);
}
@RequestMapping("/consumer/dept/findDeptList")
public List<Dept> findDeptList(){
return feignDeptService.getDeptList();
}
}
- 修改啟動類為ConsumerFeignApplication,同時添加
@EnableFeignClients
注解,啟動類代碼如下:
package com.zixin.springcloud;
import com.zixin.myrule.MyRule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
@SpringBootApplication
@EnableEurekaClient //開啟eureka客戶端
@EnableFeignClients(basePackages = {"com.zixin.springcloud"})
public class ConsumerFeignApplication {
private static final Logger logger = LoggerFactory.getLogger(ConsumerFeignApplication.class);
public static void main(String[] args) {
logger.debug("-------ConsumerFeignApplication正在啟動-----");
SpringApplication.run(ConsumerFeignApplication.class, args);
}
}
- 運行eureka-server-7001、provider-dept-8001以及consumer-dept-feign項目,訪問
http://localhost:9002/consumer/dept/findDeptList
,得到如下結果,表示以feign的方式調用服務成功