您的位置:首页 > 编程语言 > Java开发

一起来学SpringCloud之 - 服务消费者(Feign-上)

2017-09-28 13:20 736 查看
上一篇文章,讲述了Ribbon去做负载请求的服务消费者,本章讲述声明性REST客户端:Feign的简单使用方式

- Feign简介

Feign是一个声明式的Web服务客户端。这使得Web服务客户端的写入更加方便 。它具有可插拔注释支持,包括Feign注释和JAX-RS注释。Feign还支持可插拔编码器和解码器。Spring Cloud增加了对Spring MVC注释的支持,并HttpMessageConverters在Spring Web中使用了默认使用的相同方式。Spring Cloud集成了Ribbon和Eureka,在使用Feign时提供负载平衡的http客户端。

官方文档:http://cloud.spring.io/spring-cloud-static/Dalston.SR2/#spring-cloud-feign

- 准备工作

1.启动Consul,所有文章都将以Consul作为服务注册中心

2.创建
battcn-feign-hello
battcn-feign-hi


battcn-feign-hello

- pom.xml

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>


- BattcnFeignHelloApplication.java

@SpringBootApplication
@EnableDiscoveryClient
public class BattcnFeignHelloApplication {

public static void main(String[] args) {
SpringApplication.run(BattcnFeignHelloApplication.class, args);
}
}


创建一个打招呼的的Controller

- HelloController.java

@RestController
@RequestMapping("/hello")
public class HelloController {

@ResponseStatus(HttpStatus.OK)
@GetMapping
public String findStudentByName(@RequestParam("name") String name) {
// TODO:不做具体代码实现,只打印Log
return "挽歌- My Name's" + name;
}
}


- bootstrap.yml

server:
port: 8765

spring:
application:
name: battcn-feign-hello
cloud:
consul:
host: localhost
port: 8500
enabled: true
discovery:
enabled: true
prefer-ip-address: true


访问:http://localhost:8765/hello?name=Levin

结果:
挽歌- My Name's Levin
表示我们第一个服务运行一切正常

battcn-feign-hi

- pom.xml

<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>


- BattcnFeignHiApplication.java

@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.battcn.client"})
@SpringBootApplication
public class BattcnFeignHiApplication {

public static void main(String[] args) {
SpringApplication.run(BattcnFeignHiApplication.class, args);
}
}


- HelloClient.java

创建一个声明式
FeignClient
的接口
HelloClient


@FeignClient(name = "battcn-feign-hello")
public interface HelloClient {

/**
* 在新版本中,Feign 已经可以解析 RestFul 标准的接口API,比如GET POST DELETE PATCH PUT
* 旧版中
* @RequestMapping(method = RequestMethod.GET, value = "/hello")
* 或者是
* @RequestMapping(method = RequestMethod.POST, value = "/hello")
*
* 早期文章:http://blog.battcn.com/2017/07/07/springcloud-feign-analysis/
* /
@ResponseStatus(HttpStatus.OK)
@GetMapping("/hello")
String findStudentByName(@RequestParam("name") String name);
}


- HiController.java

@RestController
@RequestMapping("/hi")
public class HiController {

@Autowired
HelloClient helloClient;

@ResponseStatus(HttpStatus.OK)
@GetMapping
public String find(@RequestParam("name") String name) {
// TODO:只是演示Feign调用的方法
return "Hi," + helloClient.findStudentByName(name);
}
}


- bootstrap.yml

server:
port: 8766

spring:
application:
name: battcn-feign-hi
cloud:
consul:
host: localhost
port: 8500
enabled: true
discovery:
enabled: true
prefer-ip-address: true


访问:http://localhost:8766/hi?name=Levin

结果:
Hi,挽歌- My Name'sLevin
表示第二个服务(hi)通过FeignClient调用服务(hello)一切正常

- 源码分析

org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(Object... args)
,该方法的 args 就是我们传递的请求参数



feign.Target
->
HardCodedTarget
解析出 FeignClient中的 name 形成VIP模式
GET http://battcn-feign-hello/hello?name=Levin HTTP/1.1
然后发送请求



feign.SynchronousMethodHandler
->
this.client.execute(request, this.options);


第一个就是:
feign.Request
的一些信息,比如
header
method
body
url
等一些基本属性,因为这里是feign的Request所以我们servlet中的请求头是无法传递过来的(下篇会讲述这写小技巧)

第二个就是:
connectTimeoutMillis
readTimeoutMillis
很多人肯定不陌生



通过三面三个步骤,我们不难看出 Feign 就是解析注解然后发送HTTP(阻断器,OKHTTP模式留到下篇),有兴趣的可以自己Debug(如果该处有错误也希望各位指正)

- 说点什么

本章教程过于简单,因此代码未提交GIT(完整代码都在文章里),自行复制即可,如有问题请及时与我联系

个人QQ:1837307557

Spring Cloud中国社区①:415028731

Spring For All 社区⑤:157525002
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: