Feign 的編碼器、解碼器和客戶端都是支持自定義擴展,可以對請求以及結果和發起請求的過程進行自定義實現,Feign 默認支持 JSON 格式的編碼器和解碼器,如果希望支持其他的或者自定義格式就需要編寫自己的編碼器和解碼器,如果希望編寫自己的編碼器,需要實現 feign.codec.Encoder 接口,解碼器需要實現 feign.codec.Decoder 接口,示例如下:
自定義編碼器和解碼器
-
自定義編碼器
實現的自定義編碼器只是輸出了需要編碼的參數信息,而具體的編碼還是使用 JSON 格式,使用了 GsonEncoder 編碼器來完成具體的編碼工作,參數 object 表示需要進行編碼的對象,參數 bodyType 為 object 對象的類型,參數 template 表示的就是請求模板,該方法就是需要實現將參數 object 進行編碼並賦值到 template 請求模板中。
package org.lixue.feignclient;
import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import feign.gson.GsonEncoder;
import java.lang.reflect.Type;
public class MyEncoder implements Encoder{
private GsonEncoder gsonEncoder;
publicMyEncoder(){
gsonEncoder = new GsonEncoder();
}
public void encode(Object object,Type bodyType,RequestTemplate template) throws EncodeException{
System.out.println("encode object is class"+object.getClass().getName());
System.out.println("encode object is value"+object);
System.out.println("encode bodyType is class"+bodyType.getClass().getName());
System.out.println("encode bodyType is value"+bodyType);
gsonEncoder.encode(object,bodyType,template);
}
}
-
自定義解碼器
實現的自定義解碼器使用了 GsonDecoder 解碼器來完成具體的編碼工作,解碼器相對簡單,只需要從響應中獲取響應報文,然后按照指定的編碼格式相應的解碼並創建指定的類型實例即可。
package org.lixue.feignclient;
import feign.FeignException;
import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import feign.gson.GsonDecoder;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
public class MyDecoder implements Decoder{
private GsonDecoder gsonDecoder;
publicMyDecoder(){
gsonDecoder=newGsonDecoder();
}
public Object decode(Response response,Type type)throws IOException,DecodeException,FeignException{
return gsonDecoder.decode(response,type);
}
}
-
測試驗證
在完成自定義編碼器和解碼器的開發后,只需要在 Feign 的 builder 方法中,增加解碼器和編碼器即可,需要注意的是,如果方法請求參數或返回的不是對象,不需要進行編碼或解碼,就不能增加編碼器或解碼器,示例代碼如下:
package org.lixue.feignclient;
import feign.Feign;
import feign.Logger;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
public class Startup{
public static void main(String[]args){
HelloWorldClient speakClient=
Feign.builder().target(HelloWorldClient.class,"http://localhost:8080/");
// 參數和返回都不是對象,不需要附加編碼器和解碼器
System.out.println(speakClient.speak("isbody"));
HelloWorldClient findByIdClient=
Feign.builder().decoder(new GsonDecoder())
.target(HelloWorldClient.class,"http://localhost:8080/");
// 返回的是對象,需要附加解碼器
Person person=findByIdClient.findById(34);
System.out.println("personid="+person.getId()+"age="+person.getAge()+"name="+person.getName()+"message="+person.getMessage());
HelloWorldClient createClient=
Feign.builder().client(newMyClient())
.decoder(newMyDecoder())
.encoder(newMyEncoder())
.target(HelloWorldClient.class,"http://localhost:8080/");
Person newPerson=new Person();
newPerson.setId(3434);
newPerson.setAge(34);
newPerson.setName("343434");
newPerson.setMessage("33333333333333333");
// 參數和返回都是對象,需要附加解碼器和編碼器
ReturnValuereturnValue=createClient.create(newPerson);
System.out.println(returnValue.parseString());
}
}
自定義 Feign 客戶端
-
自定義 Feign 客戶端
Feign 使用一個 feign.Client 接口來發送請求,默認實現是使用 HttpURLConnection 連接 HTTP 服務,我們可以實現 feign.Client 接口來完成自定義 Feign 客戶端的開發,該接口只有一個方法 execute ,用於執行請求,下面實現了一個自定義的 Feign 客戶端,主要完成了請求的日志記錄,示例代碼如下:
package org.lixue.feignclient;
import feign.Client;
import feign.Request;
import feign.Response;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
public class MyClient implements Client{
public Response execute(Request request,Request.Options options)throws IOException{
System.out.println("execute request method="+request.method());
System.out.println("execute request headers");
Map<String,Collection<String>> headers=request.headers();
for(Map.Entry<String,Collection<String>> entry:headers.entrySet()){
StringBuilderstringBuilder=newStringBuilder();
for(intj=0;j<entry.getValue().size();j++){
if(stringBuilder.length()>0){
stringBuilder.append(",");
}
stringBuilder.append(entry.getValue());
}
System.out.println(entry.getKey()+":"+stringBuilder.toString());
}
byte[] body=request.body();
if(body!=null){
System.out.println("execute request body="+newString(body));
}
// 使用 Feign 默認的客戶端請求
return new Client.Default(null,null).execute(request,options);
}
}
-
測試驗證
和附加編碼器、解碼器類似,只需要在 Feign 的 builder 方法中附加自定義的客戶端即可,代碼如下:
package org.lixue.feignclient;
import feign.Feign;
import feign.Logger;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
public class Startup{
public static void main(String[]args){
HelloWorldClient findByIdClient=
Feign.builder().client(new MyClient())
.decoder(new GsonDecoder())
.target(HelloWorldClient.class,"http://localhost:8080/");
Person person=findByIdClient.findById(34);
System.out.println("personid="+person.getId()+"age="+person.getAge()+"name="+person.getName()+"message="+person.getMessage());
}
}
