微服务RESTful客户端Feign——实战篇

什么是Feign,又为什么使用Feign。Feign是一个声明式的Web Service客户端, Feign满足JSR 356规范、满足JAX-RS(Java API for RESTful)规范 ,可以快速地构建具有RESTful风格的网络请求应用。为什么用Feign,在微服务架构中, 庞杂的系统被分成了一个个微小的服务,服务与服务之间是通过HTTP接口的形式对外提供服务,Feign让服务间的调用变得简单。

官方的定义:
Feign is a Java to HTTP client binder inspired by Retrofit, JAXRS-2.0, and WebSocket. Feign's first goal was reducing the complexity of binding Denominator uniformly to HTTP APIs regardless of ReSTfulness.

它具有如下特性:
    1. 支持可插拔的注解支持,包括Feign注解和JAX-RS注解
    2. 支持可插拔的HTTP编码器和解码器
    3. 支持Hystrix和回滚
    4. 支持Ribbon的负载均衡
    5. 支持HTTP请求和响应的压缩

接下来将通过几个实战的案例讲解Feign的特性,关于Ribbon和Hystrix的部分会在接下来关于RIbbon和Hytrix的文章中整合,此篇文章暂不包括。
1 入门案例,根据FeignClient指定调用URL的方式,根据查询的参数搜索GitHub上的项目信息,下图为正常通过github查询到的关于spring-framework的搜索结果,目前有11395个项目包含spring-framework相关内容

在业务代码中,通过注解@FeignClient,指定要调用URL为https://api.github.com,Service会根据URL和@RequestMapping对应的方法转换成最终的请求地址https://api.github.com/search/repositories?q=spring-framework,然后返回对应的仓库信息,如图1所示:

图1
package com.bruce.sample.demo.service;

import com.bruce.sample.demo.config.HelloFeignServiceConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
* @Author: Bruce
* @Date: 2019/6/20 18:01
* @Version 1.0
*/

@FeignClient(name = "github-client", url = "https://api.github.com", configuration = HelloFeignServiceConfig.class)
public interface HelloFeignService {

    @RequestMapping(value = "/search/repositories", method = RequestMethod.GET)
    String searchRepo(@RequestParam("q") String queryStr);

}

然后在控制层,将业务通过注解@Autowired注入对应的调用位置,然后启动应用,输入URL:localhost:8010/search/github?string=spring-framework就可以在本地看到调用的结果,完全感知不到这是在调用远程方法。

package com.bruce.sample.demo.controller;

import com.bruce.sample.demo.service.HelloFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
* @Author: Bruce
* @Date: 2019/6/20 22:08
* @Version 1.0
*/
@RestController
public class HelloFeignController {

    @Autowired
    private HelloFeignService helloFeignService;

    @GetMapping(value = "/search/github")
    public String searchGithubRepoByStr(@RequestParam("string") String queryStr) {
        return helloFeignService.searchRepo(queryStr);
    }
}
图2

配置文件application.yml

server:
  port: 8010
  spring:
    application:
      name: feign-demo

全部代码见我的GitHub:https://github.com/Guilai1990/feigndemo/tree/master/demo
2 Spring Cloud Feign支持对请求和响应进行GZIP压缩,提高通信效率,下面演示开启GZIP压缩案例。

代码如下

package com.bruce.gzipdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients
@SpringBootApplication
public class GzipdemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(GzipdemoApplication.class, args);
    }
}
package com.bruce.gzipdemo.config;

import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* @Author: Bruce
* @Date: 2019/6/20 22:13
* @Version 1.0
*/
@Configuration
public class HelloFeignServiceConfig {
    @Bean
    Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
}
package com.bruce.gzipdemo.controller;

import com.bruce.gzipdemo.service.HelloFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
* @Author: Bruce
* @Date: 2019/6/20 22:08
* @Version 1.0
*/
@RestController
public class HelloFeignController {

    @Autowired
    private HelloFeignService helloFeignService;

    @GetMapping(value = "/search/github")
    public ResponseEntity<byte[]> searchGithubRepoByStr(@RequestParam("string") String queryStr) {
        return helloFeignService.searchRepo(queryStr);
    }
}
package com.bruce.gzipdemo.service;

import com.bruce.gzipdemo.config.HelloFeignServiceConfig;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
* @Author: Bruce
* @Date: 2019/6/20 18:01
* @Version 1.0
*/

@FeignClient(name = "github-client", url = "https://api.github.com", configuration = HelloFeignServiceConfig.class)
public interface HelloFeignService {

    @RequestMapping(value = "/search/repositories", method = RequestMethod.GET)
    ResponseEntity<byte[]> searchRepo(@RequestParam("q") String queryStr);
}

配置文件application.yml

server:
  port: 8010
  spring:
    application:
      name: feign-demo
feign:
  compression:
    request:
      enabled: true
      min-request-size: 2048
      mime-types: text/xml,appliation/json,application/xml
    response:
      enabled: true

返回结果如下图

图3

示例代码见我的GitHub: https://github.com/Guilai1990/feigndemo/tree/master/gzipdemo

3 Feign默认使用JDK原生URLConnection发送HTTP请求,没有连接池,对每个地址保持长连接。对于这点,可以通过用Apache的HTTP Client或者okhttp来替换原生的HTTP Client,进行调用调优。
例如使用HTTP Client取代Feign原始的HTTP Client,在配置文件application.yml要添加如下设置,即开启替换设置

feign:
  httpclient:
    enabled: true

全部代码详见我的github:https://github.com/Guilai1990/feigndemo/tree/master/httpclient

图4

使用okhttp替换原始的HTTP Client,在配置文件application.yml要添加如下设置,即开启替换设置

feign:
  httpclient:
    enabled: false
  okhttp:
    enabled: true

全部代码详见我的github:https://github.com/Guilai1990/feigndemo/tree/master/okhttp

图5

4.Feign当然可以和Eureka一起使用,只要配置好Eureka Client和Eureka Server, Eureka具体使用方法见上篇文章Eureka实战篇,全部代码见我的github:

https://github.com/Guilai1990/feigndemo/tree/master/eureka-server
https://github.com/Guilai1990/feigndemo/tree/master/eureka-consumer
https://github.com/Guilai1990/feigndemo/tree/master/eureka-provider
效果如下:

图6

5.Feign还可以上传文件,只需要添加依赖feign-form, feign-form-spring,详细代码见我的代码仓库:

https://github.com/Guilai1990/feigndemo/tree/master/eureka-server
https://github.com/Guilai1990/feigndemo/tree/master/feign-file-server
https://github.com/Guilai1990/feigndemo/tree/master/feign-upload-client
module: feign-file-server, feign-upload-client, eureka-server
效果图如下:
这里需要注意的是Spring Boot 2.X版本整合Swagger会出现404 Not Found错误,因此在代码中添加了如下设置,此处参考了文章解决SpringBoot2.0集成Swagger2访问404的问题

package com.bruce.feignuploadclient.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
* @Author: Bruce
* @Date: 2019/6/21 18:13
* @Version 1.0
*/
@Configuration
@EnableWebMvc
public class ApplicationExceptionAdapter extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");

        registry.addResourceHandler("/swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

效果图如下:

图7
图8

关于Feign的实战就介绍到这里,相信对Feign的功能和特性有了初步了解,接下来会写一篇文章,源码解读Feign组件,来加深对Feign的理解。

参考资料:

解决SpringBoot2.0集成Swagger2访问404的问题

猜你喜欢

转载自blog.csdn.net/u010145219/article/details/93260380