Spring Cloud應用(三)---feign使用
feign相對於httpclient與ribbon,在使用風格上更加傾向於物件導向,使用如下:
使用feign需要引入的jar包,使用pom:
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<version>8.18.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-gson</artifactId>
<version>8.18.0</version>
<scope>runtime</scope>
</dependency>
feign-gson模組是為了以json的形式與伺服器互動,使用其中的編碼器與解碼器。
當請求引數為普通字串時:
PersonClient target = Feign.builder()
.decoder(new GsonDecoder())
.encoder(new GsonEncoder())
.target(PersonClient.class, "http://localhost:8000");
// 引數為字串
Person personById = target.getPersonById(12);
System.out.println(personById);
請求引數為物件時,用json編碼後傳輸:
// 引數為物件,會由解碼器與Headers註解完成將物件以json格式傳遞給伺服器
Person person = new Person();
person.setId(22);
person.setName("hu");
person.setDesc("desc");
Person personByEntity = target.getPersonByEntity(person);
System.out.println(personByEntity);
對應的PersonClient為:
package com.hurricane.learn.feign.client;
import com.hurricane.learn.feign.entity.Person;
import feign.Headers;
import feign.Param;
import feign.RequestLine;
public interface PersonClient {
/**
* 將伺服器返回的json轉成物件,需要解碼器GsonDecoder
* 從客戶端向伺服器傳遞普通引數,格式如下
* @param id
* @return
*/
@RequestLine("GET /person/{id}")
Person getPersonById(@Param("id") int id);
/**
* 從客戶端向伺服器傳遞物件引數,需要編碼器GsonEncoder
* 並且要注意新增header註解,如下,
* 對應的伺服器端的服務介面處定義應為
* public Person getPersonByEntity(@RequestBody Person p,HttpServletRequest request)
* 注意使用RequestBody註解
* @param p
* @return
*/
@RequestLine("GET /person/entity")
@Headers("Content-Type: application/json")
Person getPersonByEntity(Person p);
//Headers標籤不可省略
@RequestLine("GET /person/entity/xml")
@Headers("Content-Type: application/xml")
Person getPersonByEntityXml(Person p);
}
在伺服器端,接收引數為簡單型別,使用@PathVariable或@RequestParam即可進行獲取,對於接收的是json時,應使用@RequestBody,這樣spring會自動將json轉換為物件(當然,接收json型別引數時,使用@RequestParam也是可以接收到的)。
feign客戶端使用的伺服器端的介面為:
@RequestMapping("/{id}")
public Person getPerson(@PathVariable("id") int id,HttpServletRequest request) {
Person person = new Person();
person.setId(id);
person.setName("hurricane");
person.setDesc(request.getRequestURI().toString());
return person;
}
@RequestMapping("/entity")
public Person getPersonByEntity(@RequestBody Person p,HttpServletRequest request) {
p.setName(p.getName()+"---from server");
return p;
}
除了使用json作為資料傳輸的格式,feign還支援xml(不止json、xml,因為feign提供了編碼器與解碼器,可以任意自定義傳輸格式,只要與伺服器端的接收匹配即可)。
在使用xml作為傳輸格式時,應注意引入類似於feign-gson的模組feign-jaxb,
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-jaxb</artifactId>
<version>8.18.0</version>
<scope>runtime</scope>
</dependency>
feign-jaxb中包含了對xml的編碼器與解碼器,feign的客戶端的定義為:
JAXBContextFactory jaxbFactory = new JAXBContextFactory.Builder().build();
PersonClient target = Feign.builder()
.encoder(new JAXBEncoder(jaxbFactory))
.decoder(new JAXBDecoder(jaxbFactory))
.target(PersonClient.class, "http://localhost:8000");
Person person = new Person();
person.setId(22);
person.setName("hurricane");
person.setDesc("desc");
Person personByEntityXml = target.getPersonByEntityXml(person);
System.out.println(personByEntityXml);
對應的PersonClient為:
//Headers標籤不可省略
@RequestLine("GET /person/entity/xml")
@Headers("Content-Type: application/xml")
Person getPersonByEntityXml(Person p);
為了配合xml的編碼器應該再Person的實體類上加入@XmlRootElement註解,如下:
@XmlRootElement
public class Person {
還有一個註解@XmlElement,可以選擇性使用,對於Person的每個屬性,要麼應有getter方法,要麼應在屬性上加入@XmlElement註解,才能讓編碼器將該屬性傳遞到伺服器端,此外@XmlElement(屬性上的)註解不應與getter方法同時存在,同時存在會拋異常說存在重複的屬性(@XmlElement放在getter方法上沒問題,但是沒必要)。若Person的一個屬性既沒有@XmlElement註解又沒有getter方法,則該屬性值無法被傳遞到伺服器端。
在伺服器端,為了能讓springboot的應用能夠接受xml形式的引數,應該加入依賴的jar包,pom為:
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-xml-provider</artifactId>
<version>2.9.5</version>
</dependency>
對應的服務端介面為:
@RequestMapping(value="/entity/xml",consumes = MediaType.APPLICATION_XML_VALUE,
produces = MediaType.APPLICATION_XML_VALUE)
public String getPersonByEntityXml(@RequestBody Person p,HttpServletRequest request) throws IOException {
System.out.println("xml請求成功");
System.out.println(p);
p.setName(p.getName()+"---from server");
return "<person><id>22</id><name>hurricane---from server</name><desc>descc</desc></person>";
}
consumes引數即使不指定,也能夠正常接收到值,但是為了伺服器的穩定性,應該對請求引數的格式做相應的限定,produces屬性必須指定,來讓springboot將Person實體類轉換為xml,返回給客戶端。
可以看到上面的伺服器介面中返回的是一個字串,這是因為spring預設轉換成的相應的xml是:
<Person><id>22</id><name>hurricane---from server</name><desc>descc</desc></Person>
注意Person標籤被大寫了,這使得feign客戶端解析失敗,為了能夠正常的接收伺服器端的xml格式的資料,才返回的字串,在實際使用中可以通過自定義的解碼器來解析,但是常規操作應該也存在,暫時還不清楚。
feign的設計使得feign使用具有很大的靈活性,客戶端、註解解析器、編碼器、解碼器都支援可插拔,如下:
PersonMyClient target = Feign.builder()
.client(new MyFeignClient()) //客戶端自定義
.contract(new MyContract()) //註解解析器自定義
.decoder(new GsonDecoder()) //解碼器自定義
.encoder(new GsonEncoder()) //編碼器自定義
.target(PersonMyClient.class, "http://localhost:8000");
具體可以參考楊恩雄的部落格:https://my.oschina.net/JavaLaw/blog?sort=time&p=5&temp=1525411026413
參考:
- 楊恩雄的視訊教程
相關文章
- Spring Cloud Feign 應用SpringCloud
- Spring Cloud feign使用okhttp3SpringCloudHTTP
- Spring Cloud Alibaba系列(三)使用feign進行服務呼叫SpringCloud
- Spring Cloud Feign 如何使用物件引數SpringCloud物件
- Spring Cloud 之 Feign.SpringCloud
- Spring Cloud應用(一)---eureka使用SpringCloud
- Spring Cloud應用(二)---ribbon使用SpringCloud
- Spring Cloud Feign設計原理SpringCloud
- Spring Cloud Alibaba 使用Feign進行服務消費SpringCloud
- Spring Cloud:使用 Feign 實現負載均衡詳解SpringCloud負載
- Spring Cloud Feign 效能最佳化SpringCloud
- Spring-Cloud之Feign原理剖析SpringCloud
- Spring Cloud實戰系列(三) - 宣告式客戶端呼叫FeignSpringCloud客戶端
- spring cloud微服務快速教程之(十四)spring cloud feign使用okhttp3--以及feign呼叫引數丟失的說明SpringCloud微服務HTTP
- 微服務Spring Cloud17_Feign9微服務SpringCloud
- Spring Cloud Alibaba(8)---Feign服務呼叫SpringCloud
- Spring Cloud Feign設計原理(轉載)SpringCloud
- Spring Cloud Feign 宣告式服務呼叫SpringCloud
- 宣告式服務呼叫 Spring Cloud FeignSpringCloud
- Spring cloud(3)-負載均衡(Feign,Ribbon)SpringCloud負載
- Spring Cloud Alibaba 使用 feign 和 rebion 進行服務消費SpringCloud
- springcloud學習筆記(二)Spring Cloud FeignSpringGCCloud筆記
- Spring Cloud Feign 熔斷機制填坑SpringCloud
- Spring Cloud Hystrix應用篇(十一)SpringCloud
- Spring Cloud Gateway應用篇(十三)SpringCloudGateway
- Spring Cloud Config應用篇(九)SpringCloud
- spring cloud微服務分散式雲架構(三)-服務消費者(Feign)SpringCloud微服務分散式架構
- Spring Cloud中,Feign常見問題總結SpringCloud
- Spring Cloud Feign的檔案上傳實現SpringCloud
- Spring Cloud Netflix—宣告性REST客戶端:FeignSpringCloudREST客戶端
- 部署Azure Spring Cloud微服務應用SpringCloud微服務
- Bug集錦-Spring Cloud Feign呼叫其它介面報錯SpringCloud
- Spring Cloud微服務-基於Eureka的feign呼叫(1)SpringCloud微服務
- Spring Cloud系列(二):Eureka應用詳解SpringCloud
- Spring Cloud整合Thrift RPC(二) - 應用案例SpringCloudRPC
- 微服務實戰SpringCloud之Spring Cloud Feign替代HTTP Client微服務SpringGCCloudHTTPclient
- spring cloud優雅的處理feign熔斷異常SpringCloud
- 擴充套件Spring Cloud Feign 實現自動降級套件SpringCloud