声明式调用Spring Cloud Feign

介绍

Spring Cloud Feign是一种简化开发的工具,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,不再需要手写RestTemplate和使用@HystrixCommand

快速入门

写在前面:
下面将逐步介绍搭建环节,由于篇幅有限,只截取重要内容,SpringBoot项目构建方式请参考【读书笔记】2.构建SpringBoot项目,所有工程基于SpringBoot 2.0,文末也会提供项目压缩包下载

项目结构预览
在这里插入图片描述

1.搭建一个公共的父项目parent

方便管理公共依赖,打包方式为POM

```xml
	<packaging>pom</packaging>
    <!-- 公共依赖-->
    <dependencies>
        <!-- 核心模块 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!-- 热部署工具 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- 测试模块 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
```

2.搭建注册中心eureka-server

需要引入spring-cloud-starter-netflix-eureka-server,然后依赖父项目,启动类和项目配置可以参考【读书笔记】3.0服务治理Spring Cloud Eureka,修改parent如下

```xml
    <parent>
        <groupId>org.cheng.demo</groupId>
        <artifactId>parent</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath> <!-- lookup parent from local -->
    </parent>
```

3.创建一个服务提供者hello-service

引入依赖:
spring-boot-starter-web,spring-cloud-starter-netflix-eureka-client 
然后创建一个HelloController,提供几个简单接口,如下
@RestController
public class HelloController {
    @GetMapping("/hello")
    public String hello()  {
        return "Hello World";
    }
    
	@GetMapping("/hello1")
    public String hello(@RequestParam("name") String name) {
        return "Hello " + name;
    }

    @GetMapping("/hello2")
    public User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age) {
        return new User(name, age);
    }

    @PostMapping("/hello3")
    public String hello(@RequestBody User user) {
        return "Hello " + user.getName() + ", " + user.getAge();
    }
}

4.创建服务消费者feign-comsumer,声明式调用

引入依赖:
spring-boot-starter-web,spring-cloud-starter-netflix-eureka-client,spring-cloud-starter-openfeign
在启动类贴上@EnableFeignClients,表明这是一个Feign客户端,开启Feign支持
再创建一个ConsumerController,引入HelloService服务,示例代码如下

@RestController
public class ConsumerController {
	@Autowired
    private HelloService  helloService;

    @GetMapping("/feign-consumer")
    public String helloConsumer() {
        return helloService.hello();
    }
}

本项目还需创建一个接口HelloService和对应的服务降级实现,内容如下

// feign客户端绑定服务(服务名不区分大小写)
@FeignClient(value = "HELLO-SERVICE", fallback = HelloServiceFallback.class)
public interface HelloService {
	 @RequestMapping("/hello")
	 String hello();
 }
 
// 消费失败时服务降级
@Component
public class HelloServiceFallback implements HelloService {
    @Override
    public String hello() {
        return "/hello, error";
    }
}

至此,一个简单的服务注册发现,声明式调用(本地化,引入HelloService)示例已完成,
此消费者同时拥有Ribbon客户端负载均衡和Hystrix的服务降级、熔断功能。

4.1参数绑定

@RequestParam(value=“xxx”),绑定请求中的Request参数
@RequestHeader(value=“xxx”),绑定请求中的Header信息
@RequestBody,绑定请求中的RequestBody或者请求响应体为对象
注:@GetMaping和@PostMaping在此版本可正常使用,当请求体为对象时,应保证存在默认构造函数
示例代码如下,

   @FeignClient(value = "HELLO-SERVICE", fallback = HelloServiceFallback.class)
public interface HelloService {

    @RequestMapping("/hello")
    String hello();

    @RequestMapping(value = "/hello1", method = RequestMethod.GET)
    String hello(@RequestParam("name") String name);

    @RequestMapping(value = "/hello2", method = RequestMethod.GET)
    User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age);

    @RequestMapping(value = "/hello3", method = RequestMethod.POST)
    String hello(@RequestBody User user);
}

4.2继承特性

问题:feign-consumer项目的接口HelloService的方法与hello-service项目的HelloController的方法完全一样,假设有多个调用方,那么每个调用方自己都要单独维护一套接口,造成代码冗余
解决:通过feign的继承特性,可以抽象这些接口,服务生产者和服务消费者复用一套接口,减少服务消费者单独定义接口的工作量

5.重构Hello-service和feign-consumer

创建一个工程hello-service-api,里面就一个接口,内容与上一小节的代码块相同,但不需要@FeignClient
hello-service和feign-consumer同时引入依赖hello-service-api
对hello-service而言,需要创建实现hello-service-api里面的接口,并且参数列表也要使用注解(缺陷?),内容如下

// feign的继承特性示例
// 实现hello-service-api的接口后,原本hello-service的controller不再需要@RequestMapping
@RestController
@Slf4j
public class RefactorHelloControllerImpl implements HelloService {

    @Override
    public String hello(@RequestParam("name") String name) {
        log.info("/hello4,{}", name);
        return "Hello " + name;
    }

    @Override
    public User hello(@RequestHeader("name") String name, @RequestHeader("age") Integer age) {
        log.info("/hello5,{},{}", name, age);
        return new User(name, age);
    }

    @Override
    public String hello(@RequestBody User user) {
        log.info("/hello6,{}", user);
        return "Hello " + user;
    }
}

对feign-consumer而言,代码简化成(此处应有掌声)

 // 继承hello-service-api的HelloService后,对服务消费者而言,不再需要像本地的HelloService定义接口
@FeignClient("HELLO-SERVICE")
public interface RefactorHelloService extends org.cheng.feign.service.HelloService {
}

不过这种继承也存在不足,如果接口有变化,必须协调下游的调用者做调整,否则调用者将无法构建项目

6.其他配置

可以为feign客户端配置日志路径,

  • 1.配置文件添加logging.level.<FeignClient的全限定类名>=DEBUG
  • 2.启动类添加 feign.Logger.level的bean

========》演示项目下载

下一篇API服务网关Spring Cloud Zuul

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火车站卖橘子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值