如何使用Feign优雅的调用远程服务

1.Feign是什么?

官网地址:https://cloud.spring.io/spring-cloud-openfeign/single/spring-cloud-openfeign.html#spring-cloud-feign

官网的解释是:

           Feign是一个声明性的Web服务客户端。它使编写Web服务客户端变得更容易。要使用Feign,请创建一个界面并对其进行注释。它具有可插入的注释支持,包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud增加了对Spring MVC注释的支持,并使用了HttpMessageConvertersSpring Web中默认使用的注释。Spring Cloud集成了Ribbon和Eureka,在使用Feign时提供负载均衡的http客户端。

 

2.为什么要使用Feign?

          我们知道,方法里面调用远程服务,使用HttpClient就可以,而且HttpClient比Feign更早出现,那我为什么还要再去使用Feign呢?首先,HttpClient前几年确实特别流行,也特别好用,但是,这个项目现在已经停止维护了,所以社区不会在那么活跃,采坑了不一定有人为你解答问题。其次,我们在使用HttpClient时,基本还需要再次封装一下get和post方法,但是,我又比较懒,我不想写那么方法。这时候,我就想到Feign。Feign 支持自定义编码器与解码器,支持失败重试与服务熔断。总之,Httpclient支持的,它基本都支持,而且实现方式更优雅。

 

3.如何基于Feign实现HttpClient的功能

3.1 添加Feign的相关依赖

<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-core</artifactId>
    <version>10.1.0</version>
</dependency>
<dependency>
    <groupId>io.github.openfeign</groupId>
    <artifactId>feign-jackson</artifactId>
    <version>9.3.1</version>
    <scope>compile</scope>
</dependency>

3.2 配置将调用服务域名

## 在yml配置文件配置服务域名,因为不同环境服务域名可能不一样
## feign远程调用地址
spring:
  feign:
    firstUrl: http://localhost:8088

3.3 添加服务方法

**
 * @author yigen shi
 * @version 1.0
 * @date 2019/7/23 17:26
 * @description
 */
@Headers({"Accept: application/json"})
public interface FirstConnector {
  
  @RequestLine("GET /api/v1/get?value={value}")
  BaseResponse<String> firstGetRequest(@Param("value") String value);
  
  @RequestLine("GET /api/v1/get/{value}")
  BaseResponse<String> anotherGetRequest(@Param("value") String value);
  
  @RequestLine("POST /api/v1/post")
  @Body("request")
  BaseResponse<String> firstPostRequest(FirstFeignRequest request);
  
}

3.4 封装Client对象以及初始化

/**
 * @author yigen shi
 * @version 1.0
 * @date 2019/7/23 17:23
 * @description
 */
@Component
public class FirstClient {

  @Value("${spring.feign.firstUrl}")
  private String firstUrl;

  @Autowired
  private FirstConnector getConnector() {
    return Feign.builder()
        // 用于解析json
        .encoder(new JacksonEncoder())
        .decoder(new JacksonDecoder())
        // 设置超时时间
        .options(new Request.Options(5000, 8000))
        // 熔断 重试次数
        .retryer(new Retryer.Default(5000, 5000, 3))
        .target(FirstConnector.class, firstUrl);
  }


  public BaseResponse<String> firstGetRequest(String value) {
    return this.getConnector().firstGetRequest(value);
  }


  public BaseResponse<String> anotherGetRequest(String value) {
    return this.getConnector().anotherGetRequest(value);
  }


  public BaseResponse<String> firstPostRequest(FirstFeignRequest request) {
    return this.getConnector().firstPostRequest(request);
  }

  
}

3.5 方法里面调用client里面的方法

/**
 * @author yigen shi
 * @version 1.0
 * @date 2019/7/23 17:38
 * @description
 */
@Api
@RestController
@RequestMapping("/api/v1/")
public class FeignController {

  private final FirstClient firstClient;

  @Autowired
  public FeignController(FirstClient firstClient) {
    this.firstClient = firstClient;
  }

  @ApiOperation("第一个feign的get方法")
  @GetMapping("/get")
  public BaseResponse<String> firstGet(@RequestParam("value") String value) {
    return firstClient.firstGetRequest(value);
  }


  @ApiOperation("另一个feign的get方法")
  @GetMapping("/get/{value}")
  public BaseResponse<String> anotherGet(@PathVariable("value") String value) {
    return firstClient.anotherGetRequest(value);
  }



  @ApiOperation("第一个feign的post方法")
  @PostMapping("/post")
  public BaseResponse<String> firstPost(@RequestBody FirstFeignRequest request){
    return firstClient.firstPostRequest(request);
  }
}

这里只是对client的方法的返回值直接进行了返回,更多情况的是,通过client调用远程服务获取结果之后,在进行封装,之后返回结果。

 

3.6 服务方方法示例(因为只是为了做示例,所以写很简单)

 @ApiOperation("对外提供get测试接口")
  @GetMapping("/get")
  public BaseResponse<String> firstGet(String value) {
    String data = "hello " + value;
    return new BaseResponse<>(data);
  }



  @ApiOperation("对外提供get测试接口")
  @GetMapping("/get/{value}")
  public BaseResponse<String> anotherGet(@PathVariable("value") String value) {
    String data = "hello " + value;
    return new BaseResponse<>(data);
  }




  @ApiOperation("对外提供post测试接口")
  @PostMapping("/post")
  public BaseResponse<String> firstPost(@RequestBody FirstFeignRequest request) {
    String data = "hello " + request.getName() + ", your id is " + request.getId();
    return new BaseResponse<>(data);
  }

 

现在,你已经实现在方法里面调用远程服务就如同调用本地方法,而且可以根据不同环境切换服务方域名,还支持服务熔断与失败重试功能,是不是觉得HttpClient优雅很多?

 

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YNO
06-17 457

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值