SpringCloud - 声明式服务调用组件Feign使用详解3(继承特性)
作者:hangge | 2020-07-30 08:10
从之前文章的样例中可以发现,当使用 Spring MVC 的注解来绑定服务接口时,我们几乎完全可以从服务提供方的 Conroller 中依靠复制操作,构建出相应的服务客户端绑定接口。但每次都要进行这些复制操作略显麻烦。
(3)编写实体类 User:
(4)编写 HelloService 接口:
(5)使用 maven 命令 install 在本地仓库创建 jar 包:

(2)创建 HelloController 类继承 hello-service-api 中定义的 HelloService 接口,并实现这三个接口:
(2)创建 RefactorHelloService 接口并继承 hello-service-api 中定义的 HelloService 接口,然后添加 @FeignClient 注解来绑定服务即可:
(3)最后在 ConsumerController 中,注入 RefactorHelloService 实例并调用即可:

在 Spring Cloud Feign 中,针对该问题提供了继承特性来帮助我们解决这些复制操作,以进一步减少编码量。下面通过样例演示如何通过 Spring Cloud Feign 的继承特性来实现 REST 接口定义的复用。
三、继承特性
1,创建基础 Maven 工程
(1)为了能够复用 DTO 与接口定义,我们创建一个基础的 Maven 工程,命名为 hello-service-api:
(2)编写 pom.xml 文件,由于我们要使用到 Spring MVC 的注解,所以需要引入 spring-boot-starter-web 依赖:
<?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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hangge</groupId>
<artifactId>hello-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>hello-service-api</name>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.6</version>
</dependency>
</dependencies>
</project>
(3)编写实体类 User:
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User {
private String name;
private Integer age;
}
(4)编写 HelloService 接口:
@RequestMapping("/refactor")
public interface HelloService {
// 带有Request参数的请求
@GetMapping("/hello1")
String hello1(@RequestParam("name") String name) ;
// 带有Header信息的请求
@GetMapping("/hello2")
User hello2(@RequestHeader("name") String name, @RequestHeader("age") Integer age);
// 带有Header信息的请求
@PostMapping("/hello3")
String hello3(@RequestBody User user);
}
(5)使用 maven 命令 install 在本地仓库创建 jar 包:

(6)去本地仓库查看下发现确实已经创建成功了:

2,改造服务提供者
(1)首先编辑 hello-service 的 pom.xml 文件,新增对 hello-service-api 的依赖:
<dependency>
<groupId>com.hangge</groupId>
<artifactId>hello-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
(2)创建 HelloController 类继承 hello-service-api 中定义的 HelloService 接口,并实现这三个接口:
- 在这个类中,除了要实现逻辑接口外,只需要增加 @RestController 注解使该类成为一个 REST 接口类就大功告成了。
- 而且通过继承的方式,在 Controller 中不再包含以往会定义的请求映射注解(如:@RequestMapping、@GetMapping、@PostMapping),而参数的注解定义在重写的时候就会自动带过来。
@RestController
public class HelloController implements HelloService {
// 带有Request参数的请求
@Override
public String hello1(@RequestParam String name) {
return "hello1 " + name;
}
// 带有Header信息的请求
@Override
public User hello2(@RequestHeader String name, @RequestHeader Integer age) {
return new User(name, age);
}
// 带有Header信息的请求
@Override
public String hello3(@RequestBody User user) {
return "hello3 " + user.getName() + ", " + user.getAge();
}
}
3,改造服务消费者
(1)首先编辑 feign-consumer 的 pom.xml 文件,同样新增对 hello-service-api 的依赖:
<dependency>
<groupId>com.hangge</groupId>
<artifactId>hello-service-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
(2)创建 RefactorHelloService 接口并继承 hello-service-api 中定义的 HelloService 接口,然后添加 @FeignClient 注解来绑定服务即可:
@FeignClient("hello-service")
public interface RefactorHelloService extends HelloService {
}
@RestController
public class ConsumerController {
@Autowired
RefactorHelloService refactorHelloService;
@GetMapping(value = "/feign-consumer")
public String helloConsumer() {
String result1 = refactorHelloService.hello1("hangge1");
User result2 = refactorHelloService.hello2("hangge2", 100);
String result3 = refactorHelloService.hello3(new User("hangge3",0));
return result1 + "<br>" + result2 + "<br>" +result3;
}
}
4,验证测试
我们启动服务中心、HELLO-SERVICE、FEIGN-CONSUMER,访问 http://localhost:9001/feign-consumer 触发对 HELLO-SERVICE 接口的调用,最终会获得如下输出,代表接口绑定和调用成功。
附:使用继承特性的优缺点
1,优点
可以将接口的定义从 Controller 中剥离,同时配合 Maven 私有仓库就可以轻易地实现接口定义的共享,不用再复制粘贴接口进行绑定,而是实现在构建期的接口绑定,从而有效减少服务客户端的绑定配置。2,缺点
由于接口在构建期间就建立起了依赖,那么接口变动就会对项目构建造成影响,可能服务提供方修改了一个接口定义,那么会直接导致客户端工程的构建失败。 所以,如果开发团队通过此方法来实现接口共享的话,建议在开发评审期间严格遵守面向对象的开闭原则,尽可能地做好前后版本的兼容,防止牵一发而动全身的后果,增加团队不必要的维护工作量。
全部评论(0)