使用Spring Cloud Feign进行服务调用

版权声明: https://blog.csdn.net/qq_18298439/article/details/83541352

在Spring Cloud Netflix栈中,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端。我们可以使用JDK原生的URLConnection、Apache的Http Client、Netty的异步HTTP Client, Spring的RestTemplate。但是用起来最方便的还是要属Feign了。

Feign简介

Feign是一种声明式、模板化的HTTP客户端。在Spring Cloud中使用Feign, 我们可以做到使用HTTP请求远程服务时能与调用本地方法一样的编码体验,开发者完全感知不到这是远程方法,更感知不到这是个HTTP请求。比如:

@Autowired
private IGeoServerFeign geoServerFeign;

String resp = geoServerFeign.publishLayerGroup(workspace, geoServerParams, token);

开发者通过geoServerFeign.publishLayerGroup()就能完成发送HTTP请求和解码HTTP返回结果并封装成对象的过程

Feign的定义

为了让Feign知道在调用方法时应该向哪个地址发请求以及请求需要带哪些参数,我们需要定义一个接口:

@FeignClient(value = "${feign.geoserver}",url="${feign.gspurl}")
public interface IGeoServerFeign {

	//发布图层组
	@PostMapping(value = "/geoserver/rest/image/layer/publish/group/{workspace}")
	String publishLayerGroup(@PathVariable String workspace,
			@RequestBody GeoServerParams geoServerParams, 
			@RequestHeader(name = "Authorization") String authorization);
	
	@DeleteMapping("/geoserver/rest/image/layer/delete/layer/{workspace}/{layername}")
	public String deleteLayer(@PathVariable String workspace,
			@PathVariable String layername, 
			@RequestHeader(name = "Authorization") String authorization);
	
	@DeleteMapping("/geoserver/rest/image/layer/delete/group/{workspace}/{layername}")
	public String deleteLayerGroup(@PathVariable String workspace,
			@PathVariable String layername,
			@RequestHeader(name = "Authorization") String authorization);

}

A: @FeignClient用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired注入。

B: @RequestMapping表示在调用该方法时需要向/group/{groupId}发送GET请求。

C: @PathVariable与SpringMVC中对应注解含义相同。

Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里。

Feign的Encoder、Decoder和ErrorDecoder


Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder)完成的。同理,将HTTP响应数据反序列化为java对象是由解码器(Decoder)完成的。

默认情况下,Feign会将标有@RequestParam注解的参数转换成字符串添加到URL中,将没有注解的参数通过Jackson转换成json放到请求体中。注意,如果在@RequetMapping中的method将请求方式未指定为POST,那么所有未标注解的参数将会被忽略,例如:

扫描二维码关注公众号,回复: 4566104 查看本文章
@RequestMapping(value = "/layergroup/{layerName}", method = RequestMethod.GET)
void save(@PathVariable("layerName") String layerName, @RequestParam("layerType") String layerType, LayerGroupTile layerGroupTile);

此时因为声明的是GET请求没有请求体,所以layerGroupTile参数就会被忽略。

在Spring Cloud环境下,Feign的Encoder*只会用来编码没有添加注解的参数*。如果你自定义了Encoder, 那么只有在编码layerGroupTile参数时才会调用你的Encoder。对于Decoder, 默认会委托给SpringMVC中的MappingJackson2HttpMessageConverter类进行解码。

只有当状态码不在200 ~ 300之间时ErrorDecoder才会被调用。

ErrorDecoder的作用是可以根据HTTP响应信息返回一个异常,该异常可以在调用Feign接口的地方被捕获到。

我们目前就通过ErrorDecoder来使Feign接口抛出业务异常以供调用者处理。

Feign的HTTP Client


Feign在默认情况下使用的是JDK原生的URLConnection发送HTTP请求,没有连接池,但是对每个地址会保持一个长连接,即利用HTTP的persistence connection 。我们可以用Apache的HTTP Client替换Feign原始的http client, 从而获取连接池、超时时间等与性能息息相关的控制能力。Spring Cloud从Brixtion.SR5版本开始支持这种替换,首先在项目中声明Apache HTTP Client和feign-httpclient依赖:

<!-- 使用Apache HttpClient替换Feign原生httpclient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>com.netflix.feign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>${feign-httpclient}</version>
        </dependency>

然后在application.yml中添加:

feign:
  httpclient:
    enabled: true

猜你喜欢

转载自blog.csdn.net/qq_18298439/article/details/83541352