天天看點

SpringCloud微服務實戰——搭建企業級開發架構(十一):內建OpenFeign用于微服務間調用

作為Spring Cloud的子項目之一,Spring Cloud OpenFeign以将OpenFeign內建到Spring Boot應用中的方式,為微服務架構下服務之間的調用提供了解決方案。首先,利用了OpenFeign的聲明式方式定義Web服務用戶端;其次還更進一步,通過內建Ribbon或Eureka實作負載均衡的HTTP用戶端。

  OpenFeign 可以使消費者将提供者提供的服務名僞裝為接口進行消費,消費者隻需使用“Service 接口+ 注解”的方式。即可直接調用 Service 接口方法,而無需再使用 RestTemplate 了。其實原理還是使用RestTemplate,而通過Feign(僞裝)成我們熟悉的習慣。

  GitEgg架構除了建立Fegin服務之外,還定義實作了消費者Fegin-api,在其他微服務調用的時候,隻需要引入Fegin-api即可直接調用,不需要在自己重複開發消費者調用接口。

1、在GitEgg-Platform工程的子工程gitegg-platform-cloud中引入spring-cloud-starter-openfeign依賴,重新install GitEgg-Platform工程,然後GitEgg-Cloud項目需要重新在IDEA中執行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 服務注冊發現-->
        <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 微服務調用解決方案-->
        <dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-starter-openfeign</artifactid>
        </dependency>
    </dependencies>

</project>
      

我們從系統架構設計方面考慮,GitEgg-Cloud下的gitegg-service作為業務邏輯處理子產品,gitegg-service-api作為微服務統一對外提供接口的子產品,這裡在測試的時候需要用到兩個微服務之間的調用,我們這裡在gitegg-service下gitegg-service-base裡面建立測試代碼,和gitegg-service-system之間互相調用。注意,這裡需要說明,gitegg-service-api并不是繼承gitegg-service做業務擴充,而是對外提供接口的抽象,比如現在有A、B、C三個系統A、B都需要調用C的同一個方法,如果按照業務邏輯來羅列代碼的話,那麼就需要在A和B中寫相同的調用方法來調用C,這裡我們抽出來一個api子產品,專門存放調用微服務C的調用方法,在使用時,A和B隻需要引入C的jar包即可直接使用調用方法。

2、在gitegg-service-system-api工程中,引入SpringBoot,SpringCloud,Swagger2的依賴,建立ISystemFeign.java和ApiSystemDTO.java,作為OpenFeign調用微服務的公共方法:

<!--?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自定義及擴充 -->
        <dependency>
            <groupid>com.gitegg.platform</groupid>
            <artifactid>gitegg-platform-boot</artifactid>
        </dependency>
        <!-- gitegg Spring Cloud自定義及擴充 -->
        <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測試Get
     *
     * @param id
     * @return
     */
    @GetMapping("/system/api/by/id")
    Result<object> querySystemById(@RequestParam("id") Long id);

    /**
     * OpenFeign測試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 = "名稱長度必須在3-20之間")
    private String name;

}

      

2、在gitegg-service-system工程中,修改SystemController.java,添加需要被微服務調用的方法:

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 = "自定義異常及傳回測試接口")
    public Result<string> exception() {
        return Result.data(systemService.exception());
    }

    @PostMapping(value = "valid")
    @ApiOperation(value = "參數校驗測試接口")
    public Result<systemdto> valid(@Valid @RequestBody SystemDTO systemDTO) {
        return Result.data(systemDTO);
    }

    @PostMapping(value = "nacos")
    @ApiOperation(value = "Nacos讀取配置檔案測試接口")
    public Result<string> nacos() {
        return Result.data(nacosMaxActiveType);
    }

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

    @PostMapping(value = "api/by/dto")
    @ApiOperation(value = "Fegin Post調用測試接口")
    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作為服務調用方:

pom.xml:

<dependencies>
        <!-- gitegg-service-system 的fegin公共調用方法 -->
        <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調用測試接口")
    public Result<object> feginById(@RequestParam("id") Long id) {
        return Result.data(systemFeign.querySystemById(id));
    }

    @PostMapping(value = "api/by/dto")
    @ApiOperation(value = "Fegin Post調用測試接口")
    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 啟動類
 */
@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、分别啟動gitegg-service-base和gitegg-service-system項目,打開浏覽器,通路http://127.0.0.1:8002/doc.html(這裡gitegg-service-base的端口設定為8002,是以通路gitegg-service-base的服務進行測試),在頁面左側菜單分别點選Fegin Get調用測試接口和Fegin Post調用測試接口,可以檢視微服務調用成功

SpringCloud微服務實戰——搭建企業級開發架構(十一):內建OpenFeign用于微服務間調用
SpringCloud微服務實戰——搭建企業級開發架構(十一):內建OpenFeign用于微服務間調用