作为 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 调用测试接口,能够查看微服务调用胜利
本文源码在 https://gitee.com/wmz1930/GitEgg 的 chapter-11 分支。