SpringCloud microservice practice -- building an enterprise level development framework: integrating OpenFeign for calls between microservices

Keywords: Java Front-end Spring Boot Vue.js Back-end

  as one of the subprojects of Spring Cloud, Spring Cloud OpenFeign provides a solution for calling between services under the microservice architecture by integrating OpenFeign into the Spring Boot application. Firstly, we use the declarative way of OpenFeign to define the Web service client; Secondly, it goes further by integrating Ribbon or Eureka to realize load balancing HTTP client.
  OpenFeign enables consumers to disguise the Service name provided by the provider as an interface for consumption. Consumers only need to use the method of "Service interface + Annotation". You can directly call the Service interface method without using RestTemplate. In fact, the principle is to use RestTemplate and Feign (disguise) as a familiar habit.
   in addition to creating a new Fegin service, the GitEgg framework also defines and implements the consumer Fegin API. When calling other microservices, you only need to introduce the Fegin API to call directly, without repeatedly developing the consumer call interface.

1. The spring cloud starter openfeign dependency is introduced into gitegg platform cloud, a sub project of gitegg platform project, and the gitegg platform project is reinstalled. Then, the gitegg cloud project needs to execute Reload All Maven Projects in the IDEA again.

<?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 Service registration discovery-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- Nacos Distributed configuration-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <!-- OpenFeign Microservice invocation solution-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

</project>

  in terms of system architecture design, gitegg service under gitegg cloud is used as a business logic processing module, and gitegg service api is used as a module for microservices to provide unified external interfaces. Calls between two microservices are required during testing. Here, we create a new test code in gitegg service base under gitegg service, And gitegg service system. Note that the gitegg service api does not inherit the gitegg service for business expansion, but provides an abstraction of the external interface. For example, there are three systems a, B and C. A and B need to call the same method of C. if the code is listed according to the business logic, you need to write the same calling method in a and B to call C, Here, we extract an api module to store the calling methods for calling microservice C. when using, a and B only need to introduce C's jar package to use the calling methods directly.
2. In the gitegg service system API project, the dependencies of SpringBoot, SpringCloud and Swagger2 are introduced, and issystemfeign.java and ApiSystemDTO.java are created as public methods for OpenFeign to call microservices:

<?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 Customization and extension -->
        <dependency>
            <groupId>com.gitegg.platform</groupId>
            <artifactId>gitegg-platform-boot</artifactId>
        </dependency>
        <!-- gitegg Spring Cloud Customization and extension -->
        <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 Test Get
     *
     * @param id
     * @return
     */
    @GetMapping("/system/api/by/id")
    Result<Object> querySystemById(@RequestParam("id") Long id);

    /**
     * OpenFeign Test 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 Must be greater than 10")
    @Max(value = 150, message = "id Must be less than 150")
    private Long id;

    @NotNull(message = "Name cannot be empty")
    @Size(min = 3, max = 20, message = "Name length must be within 3-20 between")
    private String name;
    
}

2. In gitegg service system project, modify SystemController.java and add the method to be called by microservice:

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 Interface")
    public Object list() {
        return systemService.list();
    }


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

    @GetMapping(value = "exception")
    @ApiOperation(value = "Custom exception and return test interface")
    public Result<String> exception() {
        return Result.data(systemService.exception());
    }

    @PostMapping(value = "valid")
    @ApiOperation(value = "Parameter verification test interface")
    public Result<SystemDTO> valid(@Valid @RequestBody SystemDTO systemDTO) {
        return Result.data(systemDTO);
    }

    @PostMapping(value = "nacos")
    @ApiOperation(value = "Nacos Read configuration file test interface")
    public Result<String> nacos() {
        return Result.data(nacosMaxActiveType);
    }

    @GetMapping(value = "api/by/id")
    @ApiOperation(value = "Fegin Get Call test interface")
    public Result<Object> feginById(@RequestParam("id") String id) {
        return Result.data(systemService.list());
    }

    @PostMapping(value = "api/by/dto")
    @ApiOperation(value = "Fegin Post Call test interface")
    public Result<Object> feginByDto(@Valid @RequestBody SystemDTO systemDTO) {
        return Result.data(systemDTO);
    }
}

3. Referring to the gitegg service system project, under the gitegg service base project, introduce the gitegg service system API dependency, and create BaseController.java, GitEggBaseApplication.java and bootstrap.yml as service callers:
pom.xml:

    <dependencies>
        <!-- gitegg-service-system of fegin Public call method -->
        <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 Call test interface")
    public Result<Object> feginById(@RequestParam("id") Long id) {
        return Result.data(systemFeign.querySystemById(id));
    }

    @PostMapping(value = "api/by/dto")
    @ApiOperation(value = "Fegin Post Call test interface")
    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 Startup class
 */
@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. Start gitegg service base and gitegg service system projects respectively, open the browser and visit http://127.0.0.1:8002/doc.html (here, the port of gitegg service base is set to 8002, so you can access the service of gitegg service base for testing). Click Fegin Get call test interface and Fegin Post call test interface respectively in the menu on the left of the page to view the success of micro service call

The source code of this article is in https://gitee.com/wmz1930/GitEgg chapter-11 branch of.

Posted by artiemus on Mon, 01 Nov 2021 05:56:45 -0700