Spring Cloud 入门教程(六): 用声明式REST客户端Feign调用远端HTTP服务

协变涟漪
• 阅读 146

spring Cloud 入门教程(六): 用声明式REST客户端Feign调用远端HTTP服务
首先简单解释一下什么是声明式实现?

要做一件事, 需要知道三个要素,where, what, how。即在哪里( where)用什么办法(how)做什么(what)。什么时候做(when)我们纳入how的范畴。

1)编程式实现: 每一个要素(where,what,how)都需要用具体代码实现来表示。传统的方式一般都是编程式实现,业务开发者需要关心每一处逻辑

2)声明式实现: 只需要声明在哪里(where )做什么(what),而无需关心如何实现(how)。Spring的AOP就是一种声明式实现,比如网站检查是否登录,开发页面逻辑的时候,只需要通过AOP配置声明加载页面(where)需要做检查用户是否登录(what),而无需关心如何检查用户是否登录(how)。如何检查这个逻辑由AOP机制去实现, 而AOP的登录检查实现机制与正在开发页面的逻辑本身是无关的。

在Spring Cloud Netflix栈中,各个微服务都是以HTTP接口的形式暴露自身服务的,因此在调用远程服务时就必须使用HTTP客户端。Feign就是Spring Cloud提供的一种声明式REST客户端。可以通过Feign访问调用远端微服务提供的REST接口。现在我们就用Feign来调用SERVICE-HELLOWORLD暴露的REST接口,以获取到“Hello World”信息。在使用Feign时,Spring Cloud集成了Ribbon和Eureka来提供HTTP客户端的负载均衡。

下面我们就采用Feign的方式来调用Hello World服务集群。

  1. 创建Maven工程,加入spring-cloud-starter-feign依赖

    <dependency>

    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>

    </dependency>

完整的pom文件如下:

pom.xml

  1. 创建启动类,需呀加上@EnableFeignClients注解以使用Feign, 使用@EnableDiscoveryClient开启服务自动发现

复制代码
1 package springcloud.helloworld.feign.service;
2
3 import org.springframework.boot.SpringApplication;
4 import org.springframework.boot.autoconfigure.SpringBootApplication;
5 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
6 import org.springframework.cloud.netflix.feign.EnableFeignClients;
7
8 @SpringBootApplication
9 @EnableDiscoveryClient
10 @EnableFeignClients
11 public class ServiceFeignApplication {
12 public static void main(String[] args) {
13 SpringApplication.run(ServiceFeignApplication.class, args);
14 }
15 }
复制代码

  1. 添加配置文件application.yml, 使用端口8902, 名字定义为service-feign, 并注册到eureka服务中心

复制代码
1 eureka:
2 client:
3 serviceUrl:
4 defaultZone: http://localhost:8761/eureka/
5 server:
6 port: 8902
7 spring:
8 application:
9 name: service-feign
复制代码

  1. 定义Feign:一个用@FeignClient注解的接口类,

@FeignClient用于通知Feign组件对该接口进行代理(不需要编写接口实现),使用者可直接通过@Autowired注入; 该接口通过value定义了需要调用的SERVICE-HELLOWORLD服务(通过服务中心自动发现机制会定位具体URL); @RequestMapping定义了Feign需要访问的SERVICE-HELLOWORLD服务的URL(本例中为根“/”)

复制代码
1 package springcloud.helloworld.feign.service;
2
3 import org.springframework.cloud.netflix.feign.FeignClient;
4 import org.springframework.web.bind.annotation.RequestMapping;
5 import org.springframework.web.bind.annotation.RequestMethod;
6
7 @FeignClient(value = "SERVICE-HELLOWORLD")
8 public interface HelloWorldService {
9 @RequestMapping(value = "/",method = RequestMethod.GET)
10 String sayHello();
11 }
复制代码
Spring Cloud应用在启动时,Feign会扫描标有@FeignClient注解的接口,生成代理,并注册到Spring容器中。生成代理时Feign会为每个接口方法创建一个RequetTemplate对象,该对象封装了HTTP请求需要的全部信息,请求参数名、请求方法等信息都是在这个过程中确定的,Feign的模板化就体现在这里

  1. 定义一个WebController。

注入之前通过@FeignClient定义生成的bean,

sayHello()映射到http://localhost:8902/hello, 在这里,我修改了Hello World服务的映射,将根“/”, 修改成了“/hello”。

复制代码
1 package springcloud.helloworld.feign.service;
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.web.bind.annotation.RequestMapping;
5 import org.springframework.web.bind.annotation.RequestMethod;
6 import org.springframework.web.bind.annotation.RestController;
7
8 @RestController
9 public class WebController {
10 @Autowired HelloWorldService helloWorldFeignService;
11 @RequestMapping(value = "/hello",method = RequestMethod.GET)
12 public String sayHello(){
13 return helloWorldFeignService.sayHello();
14 }
15 }
复制代码

  1. 启动Feign应用, 访问http://localhost:8902/hello, 多次刷新,可以看到和前一章Ribbon里面的应用一样, 两个Hello World服务的输出交替出现。说明通过Feign访问服务, Spring Cloud已经缺省使用了Ribbon负载均衡。
  2. 在Feign中使用Apache HTTP Client

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

复制代码
1 <!-- 使用Apache HttpClient替换Feign原生httpclient -->
2 <dependency>
3 <groupId>org.apache.httpcomponents</groupId>
4 <artifactId>httpclient</artifactId>
5 </dependency>
6 <dependency>
7 <groupId>com.netflix.feign</groupId>
8 <artifactId>feign-httpclient</artifactId>
9 <version>${feign-httpclient}</version>
10 </dependency>
复制代码
然后在application.properties中添加:
feign.httpclient.enabled=true

  1. Feign的Encoder、Decoder和ErrorDecoder

Feign将方法签名中方法参数对象序列化为请求参数放到HTTP请求中的过程,是由编码器(Encoder)完成的。同理,将HTTP响应数据反序列化为Java对象是由解码器(Decoder)完成的。默认情况下,Feign会将标有@RequestParam注解的参数转换成字符串添加到URL中,将没有注解的参数通过Jackson转换成json放到请求体中。注意,如果在@RequetMapping中的method将请求方式指定为POST,那么所有未标注解的参数将会被忽略,例如:

@RequestMapping(value = "/group/{groupId}", method = RequestMethod.GET)
void update(@PathVariable("groupId") Integer groupId, @RequestParam("groupName") String groupName, DataObject obj);
此时因为声明的是GET请求没有请求体,所以obj参数就会被忽略。

在Spring Cloud环境下,Feign的Encoder只会用来编码没有添加注解的参数。如果你自定义了Encoder, 那么只有在编码obj参数时才会调用你的Encoder。对于Decoder, 默认会委托给SpringMVC中的MappingJackson2HttpMessageConverter类进行解码。只有当状态码不在200 ~ 300之间时ErrorDecoder才会被调用。ErrorDecoder的作用是可以根据HTTP响应信息返回一个异常,该异常可以在调用Feign接口的地方被捕获到。我们目前就通过ErrorDecoder来使Feign接口抛出业务异常以供调用者处理。

以上6~7完全摘自 http://blog.csdn.net/neosmith...

点赞
收藏
评论区
推荐文章
Easter79 Easter79
4年前
springboot+springcloud微服务入门
MicroService实现技术:  用springBoot来创建单个服务,用SpringCloud来管理这些微服务。  SpringCloud的五大神兽  1.注册/服务发现——NetflixEureka    管理服务器地址和ip的  2.客服端负载均衡——NetflixRibbon\\Feign    服
Stella981 Stella981
4年前
Shiro预览
Shiro预览差不多半年之前就看到很多人在群里面讨论Shiro,由于各种原因,一直没有关注它。最近比较空闲,于是把官方的文档过一遍。所以本系列文章是根据我个人了解学习Shiro过程的笔记,可能文字上面比较粗略,望大家谅解。做一件事,我一般遵循三个步骤:What,How,When。那么要首先需要知道Shiro是什么,以及如何使用,什么场
Stella981 Stella981
4年前
Spring Boot + Spring Cloud 构建微服务系统(三):服务消费和负载(Feign)
SpringCloudFeignSpringCloudFeign是一套基于NetflixFeign实现的声明式服务调用客户端。它使得编写Web服务客户端变得更加简单。我们只需要通过创建接口并用注解来配置它既可完成对Web服务接口的绑定。它具备可插拔的注解支持,包括Feign注解、JAXRS注解。它也支持可插拔的编码器和解码器。Spri
Stella981 Stella981
4年前
Spring Http Invoker使用简介
一、SpringHTTPInvoker简介SpringHTTPinvoker 是 spring 框架中的一个远程调用模型,执行基于 HTTP 的远程调用(意味着可以通过防火墙),并使用 java 的序列化机制在网络间传递对象。这需要在远端和本地都使用Spring才行。客户端可以很轻松
Stella981 Stella981
4年前
SpringAop的简单实现
AOP当中的概念:1、切入点(Pointcut):在哪些类,哪些方法上切入(where);2、增强(Advice):早期翻译为通知,在方法执行的什么时机(when:方法前/方法后/方法前后)做什么(what:增强的功能);3、切面(Aspect):切面切入点增强,通俗点就是:在什么时机,什么地点,做
Easter79 Easter79
4年前
SpringCloud学习笔记(五)之Feign负载均衡
是什么是一个声明式WebService客户端。使用Feign能让编写WebService客户端更加简单,使用方法是定义一个接口,然后在上面添加注解,同时也支持JAXRS标准的注解。Feign也支持可拔插式的编码器和解码器。SpringCloud对Feign进行了封装,使其支持了SpringM
Easter79 Easter79
4年前
SpringCloud学习笔记(四)之Ribbon负载均衡
    在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于httprestful的。Springcloud有两种服务调用方式,一种是ribbonrestTemplate,另一种是feign。简介是基于NetflixRibbon实现的一套客户端负载均衡的工具。简单的说,Ribbon是
Stella981 Stella981
4年前
Spring Cloud微服务架构从入门到会用(三)—服务间调用Feign
微服务最重要的一个功能是服务间调用,各个服务互相依赖。比如电商系统有订单服务,有库存服务。在我们购买一件商品的时候,需要生成订单和减库存。这里我们就要用到服务间调用Feign。Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。接下来我们新建两个modu
Stella981 Stella981
4年前
React 整体感知
当我们由浅入深地认知一样新事物的时候,往往需要遵循WhyWhatHow这样一个认知过程。它们是相辅相成、缺一不可的。而了解了具体的What和How之后,往往能够更加具象地回答理论层面的Why,因此,在进入Why的探索之前,我们先整体感知一下What和How两个过程。
Stella981 Stella981
4年前
JVM系列(二) — Java垃圾收集介绍
这篇文章主要从以下几个方面介绍垃圾收集的相关知识  一、判断对象是否已死  二、主流垃圾收集算法  三、内存分配与回收策略  本章节主要从以下几个思考点着手介绍垃圾回收的相关知识:哪些内存需要回收?什么时候回收?如何回收?这也是经典的学习一个知识点的3h方法:what?when?how?上一个章节已经介绍jvm运行时数据区的内存分布,
Stella981 Stella981
4年前
Android依赖注入应用
依赖注入(DI)是一种设计模式,允许在运行时或编译时移除或改变硬编码的依赖性。使用依赖注入库可以减少编码量、把精力专注在更有价值的地方、降低维护成本。Android程序通常使用注解(Annotation,例如@Click)实现“声明式编程”和依赖注入。注:“声明式编程”告诉机器在什么地方做什么事(Where
协变涟漪
协变涟漪
Lv1
必要的时候,把一些人留在昨天吧。
文章
3
粉丝
0
获赞
0