上一篇文章,讲述了Ribbon去做负载请求的服务消费者,本章讲述声明性REST客户端: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
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.battcn</groupId> <artifactId>battcn-feign-hello</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging> <name>battcn-feign-hello</name> <description>Feign请求</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Dalston.SR2</spring-cloud.version> </properties> <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> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
package com.battcn; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class BattcnFeignHelloApplication { public static void main(String[] args) { SpringApplication.run(BattcnFeignHelloApplication.class, args); } }
创建一个打招呼的的Controller
package com.battcn.controller; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/hello") public class HelloController { @ResponseStatus(HttpStatus.OK) @GetMapping public String findStudentByName(@RequestParam("name") String name) { // TODO:不做具体代码实现,只打印Log return "挽歌- My Name's" + name; } }
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
表示我们第一个服务运行一切正常
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.battcn</groupId> <artifactId>battcn-feign-hi</artifactId> <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging> <name>battcn-feign-hi</name> <description>Feign请求</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Dalston.SR2</spring-cloud.version> </properties> <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> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
package com.battcn; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; @EnableDiscoveryClient @EnableFeignClients(basePackages = {"com.battcn.client"}) @SpringBootApplication public class BattcnFeignHiApplication { public static void main(String[] args) { SpringApplication.run(BattcnFeignHiApplication.class, args); } }
创建一个声明式 FeignClient
的接口 HelloClient
package com.battcn.client; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseStatus; /** * @author Levin * @date 2017-07-28. */ @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); }
package com.battcn.controller; import com.battcn.client.HelloClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; @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); } }
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(如果该处有错误也希望各位指正)
全文代码: http://git.oschina.net/battcn/battcn-cloud 本章教程过于简单,因此代码未提交GIT(完整代码都在文章里),自行复制即可,如有问题请及时与我联系
个人QQ:1837307557
Spring Cloud中国社区①:415028731
Spring For All 社区⑤:157525002
欢迎一起讨论与交流
转载标明出处,thanks
谢谢你请我吃糖果
支付宝
微信