javascript
SpringCloud 入门教程(六): 用声明式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
2. 創建啟動類,需呀加上@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 @SpringBootApplication9 @EnableDiscoveryClient 10 @EnableFeignClients 11 public class ServiceFeignApplication { 12 public static void main(String[] args) { 13 SpringApplication.run(ServiceFeignApplication.class, args); 14 } 15 }3. 添加配置文件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-feign4.?定義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的模板化就體現在這里
5. 定義一個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 @RestController9 public class WebController { 10 @Autowired HelloWorldService helloWorldFeignService; 11 @RequestMapping(value = "/hello",method = RequestMethod.GET) 12 public String sayHello(){ 13 return helloWorldFeignService.sayHello(); 14 } 15 }6. 啟動Feign應用, 訪問http://localhost:8902/hello, 多次刷新,可以看到和前一章Ribbon里面的應用一樣, 兩個Hello World服務的輸出交替出現。說明通過Feign訪問服務, Spring Cloud已經缺省使用了Ribbon負載均衡。
? ? ? ? ? ? ? ??
6. 在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?7.?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/article/details/52449921
總結
以上是生活随笔為你收集整理的SpringCloud 入门教程(六): 用声明式REST客户端Feign调用远端HTTP服务的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: zcmu1133(dfs+判重)
- 下一篇: ACM-ICPC 2018 徐州赛区网络