歡迎來到SpringCloud的江湖,在本章中,我們將向大家傳授如何創建SpringCloud的父子項目架構。
知識無止境,故事有好壞,文章純屬虛構,歡迎大家吐槽。
行走江湖,沒點伎倆傍身怎麼能行。本章牽扯到的技術以及工具如下:
Intellij Idea 2018.1
JDK 8
MAVEN 3.2.2
SpringBoot 1.5.13.RELEASE
Spring-Cloud Edgware.SR3
Eureka註冊中心
Fegin聲明式調用
上一篇講到了Eureka註冊中心,我們將服務都註冊到Eureka Server上。那麼問題來了,我們有多個服務,都註冊到Eureka Server上了,那麼它們之間怎麼項目調用呢?比如張三想去酒館喝酒,張三怎麼找到酒館呢?帶着問題我們往下分析。
有的同學想到了,我們可以使用RestTemplate,讓用戶去調用酒館的服務,這樣固然可以,但有的同學又說了,這樣每次都要拼長長的url,有沒有什麼更簡單的方法呢。Spring Cloud裏面已經集成了解決方案,那麼有請我們的Fegin(聲明式調用)閃亮登場。
什麼是Fegin?
Feign是一個聲明式的Web Service客戶端,它的目的就是讓Web Service調用更加簡單。Feign提供了HTTP請求的模板,通過編寫簡單的接口和插入註解,就可以定義好HTTP請求的參數、格式、地址等信息。
而Feign則會完全代理HTTP請求,我們只需要像調用方法一樣調用它就可以完成服務請求及相關處理。Feign整合了Ribbon和Hystrix(關於Hystrix我們後面再講),可以讓我們不再需要顯式地使用這兩個組件。
Fegin有什麼特性?
- 可插拔的註解支持,包括Feign註解和JAX-RS註解;
- 支持可插拔的HTTP編碼器和解碼器;
- 支持Hystrix和它的Fallback;
- 支持Ribbon的負載均衡;
- 支持HTTP請求和響應的壓縮。
使用Fegin引用依賴及基礎配置
接下來,我們便以張三去酒館喝酒的例子來介紹Fegin的使用。
首先我們先要創建用戶和酒館兩個服務。先來回顧一下這兩個服務如何創建。
探祕SpringCloud系列《第一篇章:創建Spring Cloud的Maven江湖》
準備好pub-service和user-service兩個服務。然後把它們註冊到Eureka Server裏面。因爲我們新創建的服務都需要引用Eureka Click的依賴,因爲pom文件支持繼承的特性,所以我們便把它放在頂級的pom.xml中引用。既然要使用fegin,我們需要在pom.xml添加Fegin的依賴。同樣也可以放在頂級pom.xml中。
- 修改Spring-Cloud-Edgware的pom.xml文件,添加Eureka Click和Fegin的依賴,修改後如下:
<!-- 添加Eureka Click的依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!-- 添加Fegin服務調用依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
- 修改user-service的application.yml文件,如下:
server:
port: 8000
spring:
application:
name: user-service
#註冊服務到eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
- 修改user-service的UserServiceApplication.java,添加Eureka Click的註解@EnableDiscoveryClient和Fegin服務調用的註解@EnableFeignClients
package com.maple.user;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Hack-Feng
*/
@RestController
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class UserServiceApplication {
public static void main(String[] args) {
SpringApplication.run(UserServiceApplication.class, args);
System.out.println("項目啓動成功了...");
}
@GetMapping("/test")
public String test(){
return "歡迎進入到SpringCloud江湖!";
}
}
- 同樣,修改pub-service的application.yml文件和PubServiceApplication.java
server:
port: 8001
spring:
application:
name: pub-service
#註冊服務到eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka/
模擬Fegin之間的調用
這樣,我們的兩個服務就創建好了,接下來讓我們愉快的測試一下吧。
測試用例:
- 用戶服務消費酒館服務,張三到酒館去喝酒,然後吆喝小二點菜。
- 酒館服務消費用戶服務,小二給張三上菜。
- 創建用戶服務用到的RestApi
添加Controller: UserGoPubController.java
package com.maple.user.controller;
import com.maple.user.fegin.PubServiceFegin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用戶去酒館消費Controller
* @author ZhangFZ
* @date 2020-1-14 17:24
*/
@RestController
@RequestMapping("/userGoPub")
public class UserGoPubController {
private final PubServiceFegin pubServiceFegin;
@Autowired
public UserGoPubController(PubServiceFegin pubServiceFegin) {
this.pubServiceFegin = pubServiceFegin;
}
/**
* 去酒館
*/
@GetMapping("/goPub")
public void goPub(){
System.out.println("有一天,失戀的張三想喝酒,於是他來到酒館。");
String speak = "小二,來兩壇上等的二鍋頭,兩斤牛肉,一隻烤羊腿";
System.out.println("【發送消息】:" + speak);
String result = pubServiceFegin.serviceUser(speak);
System.out.println("【收到小二回話】:" + result);
System.out.println("張三進入了漫長的等待期...");
}
/**
* 小二通知上菜
*/
@PostMapping("/notifyUser")
public String notifyUser(String speak){
System.out.println("【收到小二來話】:" + speak);
System.out.println("心情不好,回你個''");
return "";
}
}
添加Fegin服務:PubServiceFegin.java
package com.maple.user.fegin;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* @author ZhangFZ
* @date 2020-1-14 17:38
*/
@FeignClient(name = "pub-service")
public interface PubServiceFegin {
/**
* fegin調用pub-service
* @param speak 招呼小二
* @return 小二返回的話語
*/
@GetMapping("/pubServiceUser/serviceUser")
String serviceUser(@RequestParam("speak") String speak);
}
- 創建酒館服務用到的RestApi
添加Controller:PubServiceUserController.java
package com.maple.pub.controller;
import com.maple.pub.fegin.UserServiceFegin;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 酒館服務用戶Controller
* @author ZhangFZ
* @date 2020-1-14 17:26
*/
@RestController
@RequestMapping("/pubServiceUser")
public class PubServiceUserController {
private final UserServiceFegin userServiceFegin;
@Autowired
public PubServiceUserController(UserServiceFegin userServiceFegin) {
this.userServiceFegin = userServiceFegin;
}
/**
* 招呼用戶
* @param speak 用戶的招呼
* @return 返回用戶的招呼
*/
@GetMapping("/serviceUser")
public String serviceUser(String speak){
System.out.println("【小二收到張三的招呼】:" + speak);
return "好嘞,客戶您稍等...";
}
/**
* 小二上菜
*/
@GetMapping("/orderUp")
public void orderUp(){
String notifySpeak = "客官,您的兩壇二鍋頭,二斤牛肉,一隻烤羊腿,您的菜齊了";
System.out.println("【發送消息】:" + notifySpeak);
String result = userServiceFegin.notifyUser(notifySpeak);
if(StringUtils.isBlank(result)){
System.out.println("小二心想:這人居然不搭理我,一會要黑他一頓");
}else{
System.out.println("【小二收到張三的回話】:" + result);
}
}
}
添加Fegin服務:UserServiceFegin.java
package com.maple.pub.fegin;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
/**
* @author ZhangFZ
* @date 2020-1-14 17:37
*/
@FeignClient(name = "user-service")
public interface UserServiceFegin {
/**
* 小二通知用戶上菜
*/
@PostMapping("/userGoPub/notifyUser")
String notifyUser(@RequestParam("notifySpeak") String notifySpeak);
}
項目目錄如下:
Fegin調用測試
我們依次啓動eureka-server、user-service、pub-service
使用瀏覽器或post man工具,後面我們講述通過Swagger2進行接口測試和文檔管理
- 模擬張三去酒店
Get請求:http://127.0.0.1:8000/userGoPub/goPub
張三視角:
小二視角:
- 模擬小二上菜
Get請求:http://127.0.0.1:8001/pubServiceUser/orderUp
小二視角:
張三視角:
通過測試結果,我們可以看到,已經完成了服務間的聲明式調用。
本章到此結束,具體的調用原理,我們下回再說。後續文章會陸續更新,文檔會同步在CSDN和GitHub保持同步更新。
CSDN:https://blog.csdn.net/qq_34988304/category_8820134.html
Github文檔:https://github.com/hack-feng/Java-Notes/tree/master/src/note/SpringCloud
GitHub源碼:https://github.com/hack-feng/Spring-Cloud-Edgware.git