說明:該文章只是簡單描述瞭如何進行通信,並沒有關於feign的詳細註解和高級使用。(大佬看看我寫的有沒有問題也是可以的)。
流程簡述:一個程序作爲eureka服務端供其餘兩個應用註冊,另外兩個應用註冊後使用feign進行應用間通信。
使用環境:JDK 8、SpringBoot: 2.1.3、SpringCloud:Greenwich.SR1
版本不一致可能會導致莫名奇妙的錯誤。
1、eureka服務端的創建(eureka-server):
(1)打開idea創建springboot項目,在選模塊的時候記得選上下圖所示模塊:
(2)給出pom.xml和application.yml的配置文件(只要你按照(1)選了Eureka Server模塊,pom.xml應該是和我一樣的)
pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>eureka-server</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml配置:
server:
#服務端口
port: 8761
spring:
application:
name: eureka-server
eureka:
client:
# 禁止自己註冊自己
register-with-eureka: false
# 服務開啓的url
service-url:
defaultZone: http://localhost:8761/eureka/
(3)在啓動類上加上註解:@EnableEurekaServer
2、兩個eureka客戶端的創建(feign-client、feign-server):
首先創建feign-client應用
(1)創建springboot應用,在選擇模塊的時候選擇下圖所示的兩個模塊:
(2)給出pom.xml和application.yml的配置(只要你(1)中選的模塊是和我一樣的,那麼pom.xml應該也是和我一樣的)
pom.xml(feign-client)
<?xml version="1.0" encoding="UTF-8"?>
<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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>feign-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>feign-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml(feign-client):
server:
port: 8080
spring:
application:
name: feign-client
eureka:
client:
service-url:
# 註冊到服務於該url的eurekaServer
defaultZone: http://localhost:8761/eureka/
(3)在啓動類上加上註解:@EnableDiscoveryClient
然後我們以相同的方式創建feign-server應用:
給出feign-server的application.yml配置文件(pom.xml就不給了,因爲暫時不需要加東西)
server:
port: 8081
spring:
application:
name: feign-server
eureka:
client:
service-url:
# 註冊到服務於該url的eurekaServer
defaultZone: http://localhost:8761/eureka/
另外一定要給feign-server啓動類加上註解:@EnableDiscoveryClient
至此,一個簡單eureka服務端和兩個客戶端就創建好了,我們將這三個應用啓動,然後在瀏覽器上輸入:localhost:8761
看到如下畫面就代表初步準備就已經弄好了:
接下來,我們配置並使用feign進行應用間的遠程通信:
首先我們先理清思路,是feign-server要調用feign-client的服務,所以我們需要在feign-server應用裏配置feign
在feign-server應用裏配置feign:
(1)添加jar依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(2)在啓動類上加上註解:@EnableFeignClients,可以配置basePackage屬性,指定feign客戶端的包。(本應用沒有指定)
接下來我們來編寫業務類:
1、先寫feign-client的接口:
目錄結構:
ClientController類:
@Controller
@RequestMapping("/client")
public class ClientController {
//返回字符串
@GetMapping("/msg")
@ResponseBody
public String msg(){
return "你調用了Client端的服務!";
}
//返回list,在list末尾添加“client”
//必須使用Post方法,參數要加上@RequestBody
@PostMapping("/list")
@ResponseBody
public List<String> list(@RequestBody List<String> list){
list.add("client");
return list;
}
//返回對象(爲dog的name賦值)
//必須使用Post方法,參數要加上@RequestBody
@PostMapping("/dog")
@ResponseBody
public Dog setDogName(@RequestBody Dog dog){
dog.setName("clientDog");
return dog;
}
}
Dog類:
public class Dog {
private String name;
//feign返回對象時,一定要添加無參構造方法,不然會報錯:反序列化失敗
public Dog(){}
public Dog(String name){
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
2、編寫feign-server的業務類:
目錄結構
AFeignClient接口(核心,通過該接口實現向客戶端訪問):
//@FeignClient裏的name填寫需要請求的客戶端的name(註冊在eureka上的name)
//即在application.yml裏配置的spring.application.name
@FeignClient(name = "feign-client")
public interface AFeignClient {
//url必須一樣,方法名可以不同
@GetMapping("/client/msg")
String getMsgFromClient();
@PostMapping("/client/list")
List<String> getListFromClient(@RequestBody List<String> stringList);
@PostMapping("/client/dog")
Dog setDogName(@RequestBody Dog dog);
}
ServerController類:
@Controller
@RequestMapping("/server")
public class ServerController {
//@Autowired 編譯器可能會報紅,但是依然能運行(大佬告訴我爲啥...)
//有人可能會說@EnableFeignClients註解可以配置basePackages屬性指定feign-client
//我這樣做了,但是依然會報紅
//如果你的應用啓動會報錯,提示無法注入該bean,那麼你可以配置下basePackages
//例如:@EnableFeignClients(basePackages = "com.example.feignserver.client")
@Autowired
private AFeignClient aFeignClient;
//從client端獲取字符串
@RequestMapping("/msg")
public void msg(){
String msg = aFeignClient.getMsgFromClient();
System.out.println(msg);
}
//從client端獲取處理後的list
@RequestMapping("/list")
public void list(){
ArrayList<String> strList = new ArrayList<>();
strList.add("server");
List<String> listFromClient = aFeignClient.getListFromClient(strList);
System.out.println(listFromClient);
}
//從client端獲取處理的對象
@RequestMapping("/dog")
public void setDogName(){
Dog dog = aFeignClient.setDogName(new Dog());
System.out.println(dog.getName());
}
}
Dog類和client端的是一樣的,就不再給出了。
那麼接下來該測試了:
(1)同時打開三個應用,在瀏覽器上訪問localhost:8761,確認兩個客戶端都已經註冊。
(2)測試server端的返回字符串接口,在瀏覽器上訪問:localhost:8081/server/msg,feign-server的控制檯打印出如下內容:
(2)測試list接口,訪問:localhost:8081/server/list,feign-server的控制檯打印出如下內容:
(3)測試對象接口,訪問:localhost:8081/server/dog,feign-server的控制檯打印出如下內容:
我們可以看見,feign-server應用通過feign向feign-client發送請求並接受了數據。