SpringCloud微服務(wù)實(shí)戰(zhàn)——搭建企業(yè)級(jí)開(kāi)發(fā)框架(十一):集成OpenFeign用于微服務(wù)間調(diào)用

??作為Spring Cloud的子項(xiàng)目之一风皿,Spring Cloud OpenFeign以將OpenFeign集成到Spring Boot應(yīng)用中的方式,為微服務(wù)架構(gòu)下服務(wù)之間的調(diào)用提供了解決方案缠俺。首先,利用了OpenFeign的聲明式方式定義Web服務(wù)客戶端;其次還更進(jìn)一步,通過(guò)集成Ribbon或Eureka實(shí)現(xiàn)負(fù)載均衡的HTTP客戶端椿浓。
??OpenFeign 可以使消費(fèi)者將提供者提供的服務(wù)名偽裝為接口進(jìn)行消費(fèi),消費(fèi)者只需使用“Service 接口+ 注解”的方式闽晦。即可直接調(diào)用 Service 接口方法轰绵,而無(wú)需再使用 RestTemplate 了。其實(shí)原理還是使用RestTemplate尼荆,而通過(guò)Feign(偽裝)成我們熟悉的習(xí)慣。
??GitEgg框架除了新建Fegin服務(wù)之外唧垦,還定義實(shí)現(xiàn)了消費(fèi)者Fegin-api捅儒,在其他微服務(wù)調(diào)用的時(shí)候,只需要引入Fegin-api即可直接調(diào)用,不需要在自己重復(fù)開(kāi)發(fā)消費(fèi)者調(diào)用接口巧还。

1鞭莽、在GitEgg-Platform工程的子工程gitegg-platform-cloud中引入spring-cloud-starter-openfeign依賴,重新install GitEgg-Platform工程,然后GitEgg-Cloud項(xiàng)目需要重新在IDEA中執(zhí)行Reload All Maven Projects麸祷。

<?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">
    <parent>
        <artifactId>GitEgg-Platform</artifactId>
        <groupId>com.gitegg.platform</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gitegg-platform-cloud</artifactId>
    <name>${project.artifactId}</name>
    <version>${project.parent.version}</version>
    <packaging>jar</packaging>

    <dependencies>
        <!-- Nacos 服務(wù)注冊(cè)發(fā)現(xiàn)-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Nacos 分布式配置-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!-- OpenFeign 微服務(wù)調(diào)用解決方案-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

</project>

??我們從系統(tǒng)架構(gòu)設(shè)計(jì)方面考慮澎怒,GitEgg-Cloud下的gitegg-service作為業(yè)務(wù)邏輯處理模塊,gitegg-service-api作為微服務(wù)統(tǒng)一對(duì)外提供接口的模塊阶牍,這里在測(cè)試的時(shí)候需要用到兩個(gè)微服務(wù)之間的調(diào)用喷面,我們這里在gitegg-service下gitegg-service-base里面新建測(cè)試代碼,和gitegg-service-system之間相互調(diào)用走孽。注意惧辈,這里需要說(shuō)明,gitegg-service-api并不是繼承g(shù)itegg-service做業(yè)務(wù)擴(kuò)展磕瓷,而是對(duì)外提供接口的抽象盒齿,比如現(xiàn)在有A、B困食、C三個(gè)系統(tǒng)A边翁、B都需要調(diào)用C的同一個(gè)方法,如果按照業(yè)務(wù)邏輯來(lái)羅列代碼的話硕盹,那么就需要在A和B中寫相同的調(diào)用方法來(lái)調(diào)用C符匾,這里我們抽出來(lái)一個(gè)api模塊,專門存放調(diào)用微服務(wù)C的調(diào)用方法莱睁,在使用時(shí)待讳,A和B只需要引入C的jar包即可直接使用調(diào)用方法。
2仰剿、在gitegg-service-system-api工程中创淡,引入SpringBoot,SpringCloud南吮,Swagger2的依賴琳彩,新建ISystemFeign.java和ApiSystemDTO.java,作為OpenFeign調(diào)用微服務(wù)的公共方法:

<?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">
    <parent>
        <artifactId>GitEgg-Cloud</artifactId>
        <groupId>com.gitegg.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>gitegg-service-api</artifactId>
    <name>${project.artifactId}</name>
    <version>${project.parent.version}</version>
    <packaging>pom</packaging>
    <modules>
        <module>gitegg-service-base-api</module>
        <module>gitegg-service-bigdata-api</module>
        <module>gitegg-service-system-api</module>
    </modules>

    <dependencies>
        <!-- gitegg Spring Boot自定義及擴(kuò)展 -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-boot</artifactId>
        </dependency>
        <!-- gitegg Spring Cloud自定義及擴(kuò)展 -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-cloud</artifactId>
        </dependency>
        <!-- gitegg swagger2-knife4j -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-swagger</artifactId>
        </dependency>
    </dependencies>


</project>
package com.gitegg.service.system.api.feign;

import com.gitegg.platform.boot.common.base.Result;
import com.gitegg.service.system.api.dto.ApiSystemDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(name = "gitegg-service-system")
public interface ISystemFeign {

    /**
     * OpenFeign測(cè)試Get
     *
     * @param id
     * @return
     */
    @GetMapping("/system/api/by/id")
    Result<Object> querySystemById(@RequestParam("id") Long id);

    /**
     * OpenFeign測(cè)試Post
     *
     * @param apiSystemDTO
     * @return ApiSystemDTO
     */
    @PostMapping("/system/api/by/dto")
    Result<ApiSystemDTO> querySystemByDto(@RequestBody ApiSystemDTO apiSystemDTO);
}

package com.gitegg.service.system.api.dto;

import lombok.Data;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Data
public class ApiSystemDTO {

    @NotNull
    @Min(value = 10, message = "id必須大于10")
    @Max(value = 150, message = "id必須小于150")
    private Long id;

    @NotNull(message = "名稱不能為空")
    @Size(min = 3, max = 20, message = "名稱長(zhǎng)度必須在3-20之間")
    private String name;
    
}

2部凑、在gitegg-service-system工程中露乏,修改SystemController.java,添加需要被微服務(wù)調(diào)用的方法:

package com.gitegg.service.system.controller;

import com.gitegg.platform.boot.common.base.Result;
import com.gitegg.service.system.dto.SystemDTO;
import com.gitegg.service.system.service.ISystemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@RestController
@RequestMapping(value = "system")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Api(tags = "gitegg-system")
@RefreshScope
public class SystemController {

    private final ISystemService systemService;

    @Value("${spring.datasource.maxActive}")
    private String nacosMaxActiveType;

    @GetMapping(value = "list")
    @ApiOperation(value = "system list接口")
    public Object list() {
        return systemService.list();
    }


    @GetMapping(value = "page")
    @ApiOperation(value = "system page接口")
    public Object page() {
        return systemService.page();
    }

    @GetMapping(value = "exception")
    @ApiOperation(value = "自定義異常及返回測(cè)試接口")
    public Result<String> exception() {
        return Result.data(systemService.exception());
    }

    @PostMapping(value = "valid")
    @ApiOperation(value = "參數(shù)校驗(yàn)測(cè)試接口")
    public Result<SystemDTO> valid(@Valid @RequestBody SystemDTO systemDTO) {
        return Result.data(systemDTO);
    }

    @PostMapping(value = "nacos")
    @ApiOperation(value = "Nacos讀取配置文件測(cè)試接口")
    public Result<String> nacos() {
        return Result.data(nacosMaxActiveType);
    }

    @GetMapping(value = "api/by/id")
    @ApiOperation(value = "Fegin Get調(diào)用測(cè)試接口")
    public Result<Object> feginById(@RequestParam("id") String id) {
        return Result.data(systemService.list());
    }

    @PostMapping(value = "api/by/dto")
    @ApiOperation(value = "Fegin Post調(diào)用測(cè)試接口")
    public Result<Object> feginByDto(@Valid @RequestBody SystemDTO systemDTO) {
        return Result.data(systemDTO);
    }
}

3、參照gitegg-service-system工程涂邀,在gitegg-service-base工程下瘟仿,引入gitegg-service-system-api依賴,新建BaseController.java比勉、GitEggBaseApplication.java劳较、bootstrap.yml作為服務(wù)調(diào)用方:
pom.xml:

    <dependencies>
        <!-- gitegg-service-system 的fegin公共調(diào)用方法 -->
        <dependency>
            <groupId>com.gitegg.cloud</groupId>
            <artifactId>gitegg-service-system-api</artifactId>
            <version>${project.parent.version}</version>
        </dependency>
    </dependencies>

BaseController.java:

package com.gitegg.service.base.controller;

import com.gitegg.platform.boot.common.base.Result;
import com.gitegg.service.system.api.dto.ApiSystemDTO;
import com.gitegg.service.system.api.feign.ISystemFeign;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;

@RestController
@RequestMapping(value = "base")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Api(tags = "gitegg-base")
@RefreshScope
public class BaseController {

    private final ISystemFeign systemFeign;

    @GetMapping(value = "api/by/id")
    @ApiOperation(value = "Fegin Get調(diào)用測(cè)試接口")
    public Result<Object> feginById(@RequestParam("id") Long id) {
        return Result.data(systemFeign.querySystemById(id));
    }

    @PostMapping(value = "api/by/dto")
    @ApiOperation(value = "Fegin Post調(diào)用測(cè)試接口")
    public Result<Object> feginByDto(@Valid @RequestBody ApiSystemDTO systemDTO) {
        return Result.data(systemFeign.querySystemByDto(systemDTO));
    }

}

GitEggBaseApplication.java:

package com.gitegg.service.base;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;

/**
 * gitegg-base 啟動(dòng)類
 */
@EnableDiscoveryClient
@EnableFeignClients(basePackages = "com.gitegg")
@ComponentScan(basePackages = "com.gitegg")
@MapperScan("com.gitegg.*.*.mapper")
@SpringBootApplication
public class GitEggBaseApplication {

    public static void main(String[] args) {
        SpringApplication.run(GitEggBaseApplication.class,args);
    }

}

bootstrap.yml:

server:
  port: 8002
spring:
  application:
    name: gitegg-service-base
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
      config:
        server-addr: 127.0.0.1:8848
        file-extension: yaml
        prefix: gitegg-service-system
        group: DEFAULT_GROUP
        enabled: true

4驹止、分別啟動(dòng)gitegg-service-base和gitegg-service-system項(xiàng)目,打開(kāi)瀏覽器观蜗,訪問(wèn)http://127.0.0.1:8002/doc.html(這里gitegg-service-base的端口設(shè)置為8002臊恋,所以訪問(wèn)gitegg-service-base的服務(wù)進(jìn)行測(cè)試),在頁(yè)面左側(cè)菜單分別點(diǎn)擊Fegin Get調(diào)用測(cè)試接口和Fegin Post調(diào)用測(cè)試接口墓捻,可以查看微服務(wù)調(diào)用成功

image.png

image.png

本文源碼在https://gitee.com/wmz1930/GitEgg 的chapter-11分支抖仅。

GitEgg-Cloud是一款基于SpringCloud整合搭建的企業(yè)級(jí)微服務(wù)應(yīng)用開(kāi)發(fā)框架,開(kāi)源項(xiàng)目地址:

Gitee: https://gitee.com/wmz1930/GitEgg
GitHub: https://github.com/wmz1930/GitEgg

歡迎感興趣的小伙伴Star支持一下砖第。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末撤卢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子厂画,更是在濱河造成了極大的恐慌凸丸,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袱院,死亡現(xiàn)場(chǎng)離奇詭異屎慢,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)忽洛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門腻惠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人欲虚,你說(shuō)我怎么就攤上這事集灌。” “怎么了复哆?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵欣喧,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我梯找,道長(zhǎng)唆阿,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任锈锤,我火速辦了婚禮驯鳖,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘久免。我一直安慰自己浅辙,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布阎姥。 她就那樣靜靜地躺著记舆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪呼巴。 梳的紋絲不亂的頭發(fā)上泽腮,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天泊愧,我揣著相機(jī)與錄音,去河邊找鬼盛正。 笑死,一個(gè)胖子當(dāng)著我的面吹牛屑埋,可吹牛的內(nèi)容都是我干的豪筝。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼摘能,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼续崖!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起团搞,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤严望,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后逻恐,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體像吻,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年复隆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拨匆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡挽拂,死狀恐怖惭每,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情亏栈,我是刑警寧澤台腥,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站绒北,受9級(jí)特大地震影響黎侈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜镇饮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一蜓竹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧储藐,春花似錦俱济、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至辖源,卻和暖如春蔚携,著一層夾襖步出監(jiān)牢的瞬間希太,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工酝蜒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留誊辉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓亡脑,卻偏偏與公主長(zhǎng)得像堕澄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子霉咨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容