Part VI
19.9 在客戶端訪問RESTFUL服務
RestTemplate是客戶端訪問RESTFUL服務的核心類。它在概念上和SPRING的其它模版類一樣,如JdbcTemplate和JmsTemplate一起其它SPRING項目中的模版類。RestTemplate的行爲可以被定製,定製是通過提供的回調方法和配置HttpMessageConverter,HttpMessageConverter用來組織對象到HTTP請求體中並且拆開任何響應回到一個對象中。和通常的使用XML作爲消息格式一樣,SPRING提供了一個MarshallingHttpMessageConverter它使用org.springframework.oxm包中的Object-to-XML結構。這個包中提供了很多XML到對象映射技術的選擇。
這節描述怎樣使用RestTemplate和與它相關的HttpMessageConverters類。
RestTemplate
在Java中調用RESTFUL服務通常使用一個輔助類如Jakarta Commons中的HttpClient。對於如下所示,通用REST操作這個方法層次較低。
|
RestTemplate提供比較高層的方法,這些方法對應於HTTP的六個主要方法,它使得調用許多RESTFUL服務只用簡單的一行並增強REST的最佳實踐。
表19.1 RestTemplate方法一覽
HTTP方法 |
RestTemplate方法 |
DELETE |
delete(String url, String…urlVariables) |
GET |
getForObject(String url, Class<T> responseType,String…urlVariables) |
HEAD |
headForHeaders(String url, String…urlVariables) |
OPTIONS |
optionsForAllow(String url, String…urlVariables) |
POST |
postForLocation(String url, Object request, String…urlVariables) |
|
postForObject(String url, Object request, Class<T> responseType, String…uriVariables) |
PUT |
put(String url, Object request, String…urlVariables) |
RestTemplate方法的名字遵循一個名字轉換方式,第一列顯示如何調用HTTP方法,第二列顯示返回什麼。例如,getForObject方法將執行一個GET方法,轉換HTTP響應到一個你所選類型的對象並且返回該對象。postForLocation方法將會做一個POST操作,轉換給定的對象到一個HTTP請求並且返回響應新建對象可以找到的HTTP位置頭部。爲了防止處理HTTP請求時產生異常,一個RestClientException類型的異常將會被拋出,這一行爲可以通過插入另一個實現了RestTemplate的ResponseErrorHandler來改變。
傳遞到這些方法的和從這些方法返回的對象分別通過HttpMessageConverter實例被轉換到HTTP消息和來自HTTP消息。默認註冊了對主要的MIME類型的轉換,但是你同樣可以寫自己的轉換並且通過messageConverters的BEAN屬性註冊它。默認的註冊到模版上的轉換實例是ByteArrayHttpMessageConverter,StringHttpMessageConverter,FormHttpMessageConverter和SourceHttpMessageConverter。如果使用MarshallingHttpMessageConverter時你需要通過使用messageConverters的BEAN屬性來重寫這些默認實例。
每一個方法採用兩種類型的URI模版參數,或者一個字符變長的參數或者是一個Map<String,String>的形式。例如,
String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42", "21");
|
使用變長參數
Map<String, String> vars = Collections.singletonMap("hotel", "42"); String result = restTemplate.getForObject("http://example.com/hotels/{hotel}/rooms/{hotel}", String.class, vars);
|
使用Map<String,String>的形式
爲了產生一個RestTemplate的實例你可以簡單地調用默認的構造方法。這些使用來自java.net包的標準JAVA類作爲下面的實現來產生HTTP請求。這可以通過具體實現了ClientHttpRequestFactory的類來覆蓋。SPRING提供了CommonsClientHttpRequestFactory實現它使用Jakarta Commons HttpClient來產生請求。CommonsClientHttpRequestFactory使用一個可以由證書信息或連接池功能來配置的org.apache.commons.httpclient.HttpClient實例來配置。
前面使用Jakarta Commons HttpClient的例子可以直接使用RestTemplate來重寫,如下
uri = "http://example.com/hotels/{id}/bookings"; RestTemplate template = new RestTemplate(); Booking booking = // create booking object URI location = template.postForLocation(uri, booking, "1"); |
通常的回調接口是RequestCallback並且當執行方法被調用時調用。
public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor<T> responseExtractor, String... urlVariables) // also has an overload with urlVariables as a Map<String, String>. |
RequestCallback被定義如下:
public interface RequestCallback { void doWithRequest(ClientHttpRequest request) throws IOException; } |
並且允許你操縱請求頭和寫請求體。當使用執行方法時你不必擔心任何的資源管理,模版將會關閉請求和處理錯誤。關於使用執行方法和其它方法參數的意義的更多信息請參考API文檔。
HTTP Message Conversion
getForObject, postForLocation, 和 put方法傳入和返回的對象分別通過HttpMessageConverters類被轉換成了HTTP請求和來自HTTP的響應。爲了更好的瞭解它的功能 HttpMessageConverter接口如下所示:
public interface HttpMessageConverter<T> { // Indicate whether the given class is supported by this converter. boolean supports(Class<? extends T> clazz); // Return the list of MediaType objects supported by this converter. List<MediaType> getSupportedMediaTypes(); // Read an object of the given type form the given input message, and returns it. T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; // Write an given object to the given output message. void write(T t, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException; } |
框架提供對主要MIME類型的具體實現並且默認通過在客戶端的RestTemplate和在服務器端的AnnotationMethodHandlerAdapter註冊。
下面描述HttpMessageConverters的實現。默認的MIME類型在所有轉換器中使用,但是可以通過設置supportedMediaTypes 的BEAN屬性來重寫。
StringHttpMessageConverter
一個HttpMessageConverter實現可以從HTTP請求和響應中進行讀和寫字符串。默認,這種轉換支持所有的TEXT類型(text/*),並且寫的Content-Type爲text/plain。
FormHttpMessageConverter
一個HttpMessageConverter實現可以從HTTP請求和響應中進行讀和寫數據。默認,這種轉換讀和寫application/x-www-form-urlencoded的類型。表單數據讀出和寫入MultiValueMap<String, String>。
ByteArrayMessageConverter
一個HttpMessageConverter實現可以從HTTP請求和響應中進行讀和寫字節(byte)數據。默認這種轉換支持所有的類型(*/*)並且寫的Content-Type 爲application/octet-stream。這可以通過設定支持的類型和重寫getContentType(byte[])來覆寫。
MarshallingHttpMessageConverter
一個HttpMessageConverter實現可以使用在org.springframework.oxm包中的SPRING提供的Marshaller 和 Unmarshaller來讀寫XML。這種轉換在它被使用前需要一個Marshaller t Unmarshaller。這可以通過構造方法或BEAN屬性來被注射實現。默認這種轉換支持(text/xml)和(application/xml)。
SourceHttpMessageConverter
一個HttpMessageConverter實現可以從HTTP請求和響應來讀寫javax.xml.transform.Source。只有DOMSource,SAXSource和StreamSource被支持。默認,這種轉換支持(text/xml)和(application/xml)。
BufferedImageHttpMessageConverter
一個HttpMessageConverter實現可以從HTTP請求和響應來讀寫java.awt.image.BufferedImage。
這種轉換讀寫的MEDIA類型通過Java I/O API來支持