Spring Cloud-13-Feign的继承特性

上文中,初步的使用了Feign,在写HelloService接口的时候,可以发现,代码可以直接从服务提供者中复制过来.

这些可以复制的代码Spring Cloud Feign对它进行了进一步的抽象,这里就用到了Feign的继承特性,那么下面就来看下如何使用Feign的继承特性,进一步简化代码

环境搭建

新建工程

新建一个子工程,名字是hello-service-api,跟之前一样,添加到父工程下面.

创建公共接口

新建一个HelloService接口,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
@RequestMapping("helloService")
public interface HelloSerivce {

@GetMapping("/hello1")
String hello(@RequestParam("name") String name);

@GetMapping("/hello2")
User hello(@RequestHeader("name") String name, @RequestHeader("job") String job, @RequestHeader("id") Long id) throws UnsupportedEncodingException;

@PostMapping("/hello3")
String hello(@RequestBody User user);

}

这个就是我们上篇文章中的HelloService的内容,只不过加了一个请求前缀.

服务提供者修改

首先需要在服务提供者工程中,引入hello-service-api的依赖,如下:

1
2
3
4
5
6
<!-- hello service -->
<dependency>
<groupId>com.hello.service</groupId>
<artifactId>hello-service-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

然后新建一个Controller,实现刚才创建的helloService接口,具体如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@RestController
public class HelloController implements HelloSerivce {

@Override
public String hello(@RequestParam String name) {
return "name:" + name;
}

@Override
public User hello(@RequestHeader String name, @RequestHeader String job, @RequestHeader Long id) throws UnsupportedEncodingException {
return new User(id, URLDecoder.decode(name,"UTF-8"), URLDecoder.decode(job,"UTF-8"));
}

@Override
public String hello(@RequestBody User user) {
return user.getName();
}

}

实现HelloSerivce中的这几个方法, 然后方法的具体实现还是和之前的是一样的,不同的地方是,这里不需要再方法上加@RequestMapping注解,这些注解在HelloSerivce接口中都有了

方法中的参数@RequestHeader@RequestBody注解还是要添加,@RequestParam注解可以不添加

服务消费者修改

首先需要把hello-service-api的依赖引进来:

1
2
3
4
5
<dependency>
<groupId>com.hello.service</groupId>
<artifactId>hello-service-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>

消费者中新建一个HelloService2,然后继承上面创建的HelloSerivce,代码如下:

1
2
3
@FeignClient("eureka-client")
public interface HelloService2 extends HelloSerivce {
}

这个接口是不需要添加任何方法,方法都在父接口中,这里只需要在类上面添加@FeignClient注解,来绑定服务即可.

最后在Controller中提供调用的接口:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RestController
@RequestMapping("/hello")
public class HelloController {
@Autowired
private HelloService2 helloService;


@GetMapping("/hello1")
public String hello1(){
return helloService.hello("张三");
}

@GetMapping("/hello2")
public User hello2() throws UnsupportedEncodingException {
return helloService.hello(URLEncoder.encode("张三", "UTF-8"), URLEncoder.encode("测试", "UTF-8"), 1L);
}

@GetMapping("/hello3")
public String hello3(){
User user = new User(1L, "张三", "开发");
return helloService.hello(user);
}
}

测试

依次启动,服务注册中心,服务提供者,消费者,然后请求上面这个controller中的几个接口. 看一下返回值:

image

image

image

总结

总的实现过程呢就是先创建一个提供者和消费者公用的接口, 然后提供者的Controller实现公共接口, 然后消费者创建接口继承这个公共接口.

这种方式用起来方便,但是耦合度太高,此时如果服务提供者修改了一个接口的定义,服务消费者可能也得跟着变化,进而带来很多未知的工作量,因此小伙伴们在使用继承特性的时候,要慎重考虑.