一、簡述
Feign是一個聲明式WebService客戶端。使用Feign能讓編寫Web Service客戶端更加簡單。Feign是對Ribbon的包裝,Feign集成了Ribbon。
前面在使用Ribbon+RestTemplate時,利用RestTemplate對http請求的封裝處理,形成了一套模版化的調用方法。但是在實際開發中,由於對服務依賴的調用可能不止一處,往往一個接口會被多處調用,所以通常都會針對每個微服務自行封裝一些客戶端類來包裝這些依賴服務的調用。所以,Feign在此基礎上做了進一步封裝,由他來幫助我們定義和實現依賴服務接口的定義。在Feign的實現下,我們只需創建一個接口並使用註解的方式來配置它,即可完成對服務提供方的接口綁定,簡化了使用Spring cloud Ribbon時,自動封裝服務調用客戶端的開發量。
個人理解:feign也是客戶端的負載均衡,它包裝了ribbon。ribbon負載均衡是面向整個服務的,而feign是面向服務的接口,這樣更利於我們這些面向接口編程的人。它的原理就是寫一個調用服務提供者的接口,然後客戶端訪問時在controller中調用這個接口。就是在服務端、消費端中間又加了一層接口,這個接口通過feign來訪問服務端並實現接口的負載均衡。
二、配置feign負載均衡
1.創建module
在父項目中新建module:microservice-consumer-feign8080
2.添加依賴
pom:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.syr.springcloud</groupId>
<artifactId>microservice</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>microservice-consumer-feign8080</artifactId>
<dependencies>
<dependency>
<groupId>com.syr.springcloud</groupId>
<artifactId>microservice-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 修改後立即生效,熱部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!-- Ribbon相關 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>
</project>
3.配置信息
server:
port: 8080
eureka:
register-with-eureka: false
client:
service-url:
defaultZone: http://eureka2001.com:2001/eureka/,http://eureka2002.com:2002/eureka/,http://eureka2003.com:2003/eureka/
4.創建接口
注意:接口上要標註@FeignClient(value = “microservicecloud-provider”)
其中value值爲需要訪問的服務名稱(eureka上註冊的服務名稱)
package com.syr.consumer.service;
import java.util.List;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import com.syr.api.entity.User;
@RequestMapping("users")
@FeignClient(value = "microservicecloud-provider")
public interface UserService {
@GetMapping(value = "{id}")
public User get(@PathVariable("id") int id) ;
@GetMapping
public List<User> get() ;
@PostMapping
public boolean post(@RequestBody User user) ;
@DeleteMapping("{id}")
public boolean delete(@PathVariable("id") int id);
@PutMapping
public boolean put(@RequestBody User user);
}
5.創建controller
注意:該controller中,訪問路徑不應該與service接口中的路徑一樣,會報錯。所有我在@RequestMapping("/consumer/users")
中添加了一層consumer
package com.syr.consumer.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
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 com.syr.api.entity.User;
import com.syr.consumer.service.UserService;
@RestController
@RequestMapping("/consumer/users")
public class UserController {
@Autowired
private UserService service;
@GetMapping(value = "{id}")
public User get(@PathVariable("id")int id) {
User user=service.get(id);
return user;
}
@GetMapping
public List<User> get() {
List<User> users=service.get();
return users;
}
@PostMapping
public boolean post(@RequestBody User user) {
boolean b = service.post(user);
return b;
}
@DeleteMapping("{id}")
public boolean delete(@PathVariable("id") int id) {
boolean b = service.delete(id);
return b;
}
@PutMapping
public boolean put(@RequestBody User user) {
boolean b = service.put(user);
return b;
}
}
6.開啓feign
basePackages是feign接口所在包
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = "com.syr.consumer.service")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
7.測試
測試成功
8.通用
一些需要共用的服務,它的fiegn接口應放在通用項目中如:microservice-api
9.與ribbon的對比
ribbon是面向整個服務,而feign面向服務的接口
ribbon中,由於restTemplate的 delete、put方法是沒有返回值的,所以執行後也不知道是否成功。而feign是feign查找服務controller中的方法,也就是對應的是方法,是可以有返回值的。