作为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调用测试接口,可以查看微服务调用成功
image.png
image.png