探祕SpringCloud系列《第三篇章:使用Fegin聲明式服務調用》

歡迎來到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中。

  1. 修改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>
  1. 修改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/
  1. 修改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江湖!";
    }
}
  1. 同樣,修改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之間的調用

這樣,我們的兩個服務就創建好了,接下來讓我們愉快的測試一下吧。
測試用例:

  1. 用戶服務消費酒館服務,張三到酒館去喝酒,然後吆喝小二點菜。
  2. 酒館服務消費用戶服務,小二給張三上菜。
  1. 創建用戶服務用到的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);
}
  1. 創建酒館服務用到的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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章