瘋狂Spring Cloud連載(11)——Feign的編碼器與解碼器

本文節選自《瘋狂Spring Cloud微服務架構實戰》html

京東購買地址:https://item.jd.com/12256011.htmljava

噹噹網購買地址:http://product.dangdang.com/25201393.htmlgit

Spring Cloud教學視頻:https://my.oschina.net/JavaLaw/blog/1552993web

Spring Cloud電子書:https://my.oschina.net/JavaLaw/blog/1570383spring

        本文要點json

             Feign編碼器與解碼器架構

11.1 Feign的編碼器與解碼器

        本小節全部的案例都是單獨使用Feign,Feign在Spring Cloud的使用將在後面章節講述,請讀者注意該細節。app

5.2.1 編碼器

        向服務發送請求的過程當中,有些狀況須要對請求的內容進行處理。例如服務端發佈的服務接收的是JSON格式參數,而客戶端使用的是對象,這種狀況就可使用編碼器,將對象轉換爲JSON字符串。ide

        爲服務端編寫一個REST服務,處理POST請求,請見代碼清單5-7。spring-boot

        代碼清單5-7:codes\05\5.1\rest-server\src\main\java\org\crazyit\cloud\MyController.java

/**
	 * 參數爲JSON
	 */
	@RequestMapping(value = "/person/create", method = RequestMethod.POST, 
        consumes = MediaType.APPLICATION_JSON_VALUE)
	@ResponseBody
	public String createPerson(@RequestBody Person person) {
		System.out.println(person.getName() + "-" + person.getAge());
		return "Success, Person Id: " + person.getId();
	}

        控制器中,發佈了一個「/person/create」的服務,須要傳入JSON格式的請求參數。在客戶端中,要調用該服務,先編寫接口,再使用註解進行修飾,請見代碼清單5-8。

        代碼清單5-8:codes\05\5.2\feign-use\src\main\java\org\crazyit\feign\PersonClient.java

public interface PersonClient {

    @RequestLine("POST /person/create")
    @Headers("Content-Type: application/json")
    String createPerson(Person person);

    @Data
    class Person {
        Integer id;
        String name;
        Integer age;
        String message;
    }
}

        注意在客戶端的服務接口中,使用了@Headers註解,聲明請求的內容類型爲JSON,接下來再編寫運行類,如代碼清單5-9。

        代碼清單5-9:codes\05\5.2\feign-use\src\main\java\org\crazyit\feign\EncoderTest.java

/**
 * 運行主類
 * @author 楊恩雄
 *
 */
public class EncoderTest {

	public static void main(String[] args) {
		// 獲取服務接口
		PersonClient personClient = Feign.builder()
				.encoder(new GsonEncoder())
				.target(PersonClient.class, "http://localhost:8080/");
		// 建立參數的實例
		Person person = new Person();
		person.id = 1;
		person.name = "Angus";
		person.age = 30;
		String response = personClient.createPerson(person);
		System.out.println(response);
	}
}

        運行類中,在建立服務接口實例時,使用了encoder方法來指定編碼器,本案例使用了Feign提供的GsonEncoder類,該類會在發送請求過程當中,將請求的對象轉換爲JSON字符串。Feign支持插件式的編碼器,若是Feign提供的編碼器沒法知足要求,還可使用自定義的編碼器,這部份內容在後面章節講述。啓動服務,運行代碼清單5-9,可看到服務已經調用成功,運行後輸出以下:

Success, Person Id: 1

5.2.2 解碼器

        編碼器是對請求的內容進行處理,解碼器則會對服務響應的內容進行處理,例如解析響應的JSON或者XML字符串,轉換爲咱們所須要的對象,在代碼中經過如下的代碼片段設置解碼器:

PersonClient personService = Feign.builder()
.decoder(new GsonDecoder())
.target(PersonClient.class, "http://localhost:8080/");

        在前面章節中,咱們已經使用過GsonDecoder解碼器,在此再也不做贅述。

5.2.3 XML的編碼與解碼

        除了支持JSON的處理外,Feign還爲XML的處理了提供編碼器與解碼器,可使用JAXBEncoder與JAXBDecoder來進行編碼與解碼。爲服務端添加發布XML的接口,請見代碼清單5-10。

        代碼清單5-10:codes\05\5.1\rest-server\src\main\java\org\crazyit\cloud\MyController.java

/**
	 * 參數與返回值均爲XML
	 */
	@RequestMapping(value = "/person/createXML", method = RequestMethod.POST, 
			consumes = MediaType.APPLICATION_XML_VALUE, 
			produces = MediaType.APPLICATION_XML_VALUE)
	@ResponseBody
	public String createXMLPerson(@RequestBody Person person) {
		System.out.println(person.getName() + "-" + person.getId());
		return "<result><message>success</message></result>";
	}

        在服務端發佈的服務方法中,聲明瞭傳入的參數爲XML。須要注意的是,服務端項目「rest-server」使用的是「spring-boot-starter-web」進行構建,默認狀況下不支持XML接口,調用接口時會獲得如下異常信息:

{"timestamp":1502705981406,"status":415,"error":"Unsupported Media Type","exception":"org.springframework.web.HttpMediaTypeNotSupportedException","message":"Content type 'application/xml;charset=UTF-8' not supported","path":"/person/createXML"}

        爲服務端的pom.xml加入如下依賴便可解決該問題:

<dependency>
    <groupId>com.fasterxml.jackson.jaxrs</groupId>
    <artifactId>jackson-jaxrs-xml-provider</artifactId>
    <version>2.9.0</version>
</dependency>

        編寫客戶端時,先定義好服務接口以及對象,接口請見代碼清單5-11。

        代碼清單5-11:codes\05\5.2\feign-use\src\main\java\org\crazyit\feign\PersonClient.java

public interface PersonClient {

	@RequestLine("POST /person/createXML")
	@Headers("Content-Type: application/xml")
	Result createPersonXML(Person person);

	@Data
	@XmlRootElement
	class Person {
		@XmlElement
		Integer id;
		@XmlElement
		String name;
		@XmlElement
		Integer age;
		@XmlElement
		String message;
	}

	@Data
	@XmlRootElement
	class Result {
		@XmlElement
		String message;
	}
}

        在接口中,定義了「Content-Type」爲XML,使用了JAXB的相關注解來修飾Person與Result。接下來,只須要調用createPersonXML方法便可請求服務,請見代碼清單5-12。

        代碼清單5-12:codes\05\5.2\feign-use\src\main\java\org\crazyit\feign\XMLTest.java

package org.crazyit.feign;

import org.crazyit.feign.PersonClient.Person;
import org.crazyit.feign.PersonClient.Result;

import feign.Feign;
import feign.jaxb.JAXBContextFactory;
import feign.jaxb.JAXBDecoder;
import feign.jaxb.JAXBEncoder;

public class XMLTest {

	public static void main(String[] args) {
		JAXBContextFactory jaxbFactory = new JAXBContextFactory.Builder().build();
		// 獲取服務接口
		PersonClient personClient = Feign.builder()
				.encoder(new JAXBEncoder(jaxbFactory))
				.decoder(new JAXBDecoder(jaxbFactory))
				.target(PersonClient.class, "http://localhost:8080/");
		// 構建參數
		Person person = new Person();
		person.id = 1;
		person.name = "Angus";
		person.age = 30;
		// 調用接口並返回結果
		Result result = personClient.createPersonXML(person);
		System.out.println(result.message);
	}
}

        本小節的請求有一點特殊,請求服務時傳入參數爲XML、返回的結果也是XML,目的是爲了能使編碼與解碼一塊兒使用。開啓服務,運行代碼清單5-12,能夠看到服務端與客戶端的輸出。

5.2.4 自定義編碼器與解碼器

        根據前面的兩小節可知,Feign的插件式編碼器與解碼器,能夠對請求以及結果進行處理,若是對於一些特殊的要求,可使用自定義的編碼器與解碼器。實現自定義編碼器,須要實現Encoder接口的encode方法,而對於解碼器,則要實現Decoder接口的decode方法,例如如下的代碼片段:

package org.crazyit.feign;

import java.lang.reflect.Type;

import feign.RequestTemplate;
import feign.codec.EncodeException;
import feign.codec.Encoder;

public class MyEncoder implements Encoder {

	public void encode(Object object, Type bodyType, RequestTemplate template)
			throws EncodeException {
		// 實現本身的Encode邏輯
	}
}

        在使用時,調用Feign的API來設置編碼器或者解碼器便可,實現較爲簡單,在此再也不贅述。

本文節選自《瘋狂Spring Cloud微服務架構實戰》

Spring Cloud教學視頻:https://my.oschina.net/JavaLaw/blog/1552993

Spring Cloud電子書:https://my.oschina.net/JavaLaw/blog/1570383

本書代碼共享地址:https://gitee.com/yangenxiong/SpringCloud

相關文章
相關標籤/搜索