
Spring 的 RestTemplate 是一個健壯的、流行的基于 Java 的 REST 客戶端。Spring for Android RestTemplate Module 提供了一個在 Android 環(huán)境中工作的 RestTemplate 版本。
該類是 Spring for Android RestTemplate 庫的核心。它在概念上類似于其他 Spring 項目組合項目中的其他模板類。RestTemplate 的行為是通過提供回調(diào)方法和配置用于將對象封送到 HTTP 請求正文中以及將任何響應取消封送回對象來自定義的。創(chuàng)建新實例時,構(gòu)造函數(shù)將設置多個構(gòu)成 RestTemplate 功能的支持對象。??RestTemplate?
???HttpMessageConverter?
???RestTemplate?
?
(資料圖)
下面概述了 中支持的功能。??RestTemplate?
?
??RestTemplate?
?提供了一個用于發(fā)出 RESTful HTTP 請求的抽象,并在內(nèi)部為這些請求使用本機 Android HTTP 客戶端庫。Android 上有兩個本機 HTTP 客戶端,標準 J2SE 設施和HttpComponents HttpClient。標準的 JS2SE 工具可通過 獲得,而 HttpClient 可通過 使用。對原生 HttpClient 4.0 的支持已被棄用,取而代之的是 HttpClient 4.3 的 Android 端口。創(chuàng)建新實例時使用的默認值因運行應用程序的 Android 版本而異。??RestTemplate?
???SimpleClientHttpRequestFactory?
???HttpComponentsAndroidClientHttpRequestFactory?
???ClientHttpRequestFactory?
???RestTemplate?
?
Google 建議在Android 2.3(Gingerbread)及更高版本上使用 J2SE 工具,而以前的版本應使用 HttpComponents HttpClient。根據(jù)此建議,檢查運行應用的 Android 版本,并使用相應的 .若要使用特定實例,必須將新實例傳遞到構(gòu)造函數(shù)中,或調(diào)用現(xiàn)有實例。??RestTemplate?
???ClientHttpRequestFactory?
???ClientHttpRequestFactory?
???RestTemplate?
???setRequestFactory(ClientHttpRequestFactory requestFactory)?
???RestTemplate?
?
Spring for Android 還包括對第三方 HTTP 客戶端庫的支持。適用于Android的HttpClient 4.3與所有版本的Android兼容,并且可以通過簡單地將依賴項包含在項目中來用作本機客戶端的替代方案。如果 Spring for Android 檢測到 HttpClient 4.3,那么它會自動將其配置為默認 .HttpClient 4.3 對 Android 中包含的原生 HttpClient 4.0 進行了大量錯誤修復和改進。??ClientHttpRequestFactory?
?
dependencies { compile("org.apache.httpcomponents:httpclient-android:$httpClientVersion")}
基于OkHttp的附加功能可作為兩個本機客戶端的替代方法。 可以配置為通過構(gòu)造函數(shù)或通過設置屬性來使用。它在Android 2.3(Gingerbread)及更高版本上受支持,但是為了使用它,您必須在項目中包含OkHttp依賴項。??ClientHttpRequestFactory?
???RestTemplate?
???OkHttpRequestFactory?
???RestTemplate?
???requestFactory?
?
dependencies { compile("com.squareup.okhttp:okhttp-urlconnection:$okHttpVersion")}
??RestTemplate?
?支持發(fā)送和接收使用 gzip 壓縮編碼的數(shù)據(jù)。HTTP 規(guī)范允許在標頭字段中使用其他值,但目前僅支持 gzip 壓縮。??Accept-Encoding?
???RestTemplate?
?
Spring for Android RestTemplate 中的 JSON 封送處理對象需要使用第三方 JSON 映射庫。Spring for Android 支持兩個庫,Jackson 2.x?和Google Gson。雖然 Jackson 是一個眾所周知的 JSON 解析庫,但 Gson 庫更小,這將導致打包時 Android 應用程序更小。
在 Spring for Android RestTemplate 中反對 XML 封送處理需要使用第三方 XML 映射庫。簡單 XML 序列化程序用于提供此封送處理功能。
有幾種方法可以在您的 Android 應用中包含外部 jar。您可以使用 Gradle 或 Maven 進行依賴關系管理,也可以手動下載它們并將其包含在應用的文件夾中。??libs/?
?
Android Studio 和New Build Systemfor Android 提供了一個用于構(gòu)建Android應用程序的 Gradle 插件。Gradle 提供了內(nèi)置的依賴項管理,可用于將 Spring for Android 依賴項包含在項目中。
將 spring-android-rest-template 依賴項添加到您的文件中:??build.gradle?
?
dependencies { compile("org.springframework.android:spring-android-rest-template:${version}")}
Maven可用于管理依賴項和構(gòu)建Android應用程序。有關更多信息,請參閱Spring for Android 和 Maven部分。可能需要其他依賴項,具體取決于您在 RestTemplate 中使用的 HTTP 消息轉(zhuǎn)換器。有關詳細信息,請參閱消息轉(zhuǎn)換器部分。
將 spring-android-rest-template 依賴項添加到您的文件中:??pom.xml?
?
org.springframework.android spring-android-rest-template ${spring-android-version}
為了在Android應用程序中使用RestTemplate,您必須在文件夾中包含以下Spring for Android jars。??libs/?
?
?spring-android-rest-template-{version}.jar?
???spring-android-core-{version}.jar?
?如果使用 Ant 構(gòu)建項目,Ant 將自動包含位于項目根目錄中的任何 jar。但是,在 Eclipse 中,您必須手動將 jar 添加到構(gòu)建路徑中。按照以下步驟將 jar 添加到 Eclipse 中的現(xiàn)有 Android 項目中。??libs/?
?
?libs/?
?右鍵單擊(按住命令單擊)第一個 jar。選擇子菜單。??BuildPath?
?從上下文菜單中選擇。??Add to Build Path?
?對每個罐子重復這些步驟。下面列出了構(gòu)造函數(shù)。默認構(gòu)造函數(shù)包括一組標準的消息正文轉(zhuǎn)換器。有關默認轉(zhuǎn)換器的列表,請參閱HTTP 消息轉(zhuǎn)換部分。??RestTemplate?
?
RestTemplate();RestTemplate(ClientHttpRequestFactory requestFactory);RestTemplate(List> messageConverters);
如果要指定替代項,例如 ,則可以將其傳遞給參數(shù)。??ClientHttpRequestFactory?
???OkHttpClientHttpRequestFactory?
???requestFactory?
?
OkHttpClientHttpRequestFactory requestFactory = new OkHttpClientHttpRequestFactory();RestTemplate template = new RestTemplate(ClientHttpRequestFactory requestFactory);
??RestTemplate?
?提供與六個主要 HTTP 方法中的每一個相對應的高級方法。這些方法可以輕松調(diào)用許多 RESTful 服務并強制實施 REST 最佳實踐。
方法的名稱遵循命名約定,第一部分指示正在調(diào)用的 HTTP 方法,第二部分指示返回的內(nèi)容。例如,該方法將執(zhí)行 GET,將 HTTP 響應轉(zhuǎn)換為您選擇的對象類型并返回該對象。該方法將執(zhí)行 POST,將給定對象轉(zhuǎn)換為 HTTP 請求,并返回響應 HTTP 位置標頭,可在其中找到新創(chuàng)建的對象。如果處理 HTTP 請求發(fā)生異常,將引發(fā)該類型的異常。可以通過將另一個實現(xiàn)插入到??RestTemplate?
???getForObject()?
???postForLocation()?
???RestClientException?
???ResponseErrorHandler?
???RestTemplate.?
?
有關及其相關方法的更多信息,請參閱API Javadoc??RestTemplate?
?
public void delete(String url, Object... urlVariables) throws RestClientException;public void delete(String url, MapurlVariables) throws RestClientException;public void delete(URI url) throws RestClientException;
publicT getForObject(String url, Class responseType, Object... urlVariables) throws RestClientException;public T getForObject(String url, Class responseType, Map urlVariables) throws RestClientException;public T getForObject(URI url, Class responseType) throws RestClientException;public ResponseEntity getForEntity(String url, Class responseType, Object... urlVariables);public ResponseEntity getForEntity(String url, Class responseType, Map urlVariables);public ResponseEntity getForEntity(URI url, Class responseType) throws RestClientException;
public HttpHeaders headForHeaders(String url, Object... urlVariables) throws RestClientException;public HttpHeaders headForHeaders(String url, MapurlVariables) throws RestClientException;public HttpHeaders headForHeaders(URI url) throws RestClientException;
public SetoptionsForAllow(String url, Object... urlVariables) throws RestClientException;public Set optionsForAllow(String url, Map urlVariables) throws RestClientException;public Set optionsForAllow(URI url) throws RestClientException;
public URI postForLocation(String url, Object request, Object... urlVariables) throws RestClientException;public URI postForLocation(String url, Object request, MapurlVariables);public URI postForLocation(URI url, Object request) throws RestClientException;public T postForObject(String url, Object request, Class responseType, Object... uriVariables);public T postForObject(String url, Object request, Class responseType, Map uriVariables);public T postForObject(URI url, Object request, Class responseType) throws RestClientException;public ResponseEntity postForEntity(String url, Object request, Class responseType, Object... uriVariables);public ResponseEntity postForEntity(String url, Object request, Class responseType, Map uriVariables) throws RestClientException;public ResponseEntity postForEntity(URI url, Object request, Class responseType) throws RestClientException;
public void put(String url, Object request, Object... urlVariables) throws RestClientException;public void put(String url, Object request, MapurlVariables) throws RestClientException;public void put(String url, Object request, Map urlVariables) throws RestClientException;
傳遞給方法 、 和 從方法返回的對象被實例轉(zhuǎn)換為 HTTP 請求和 HTTP 響應。界面如下所示,讓您更好地了解其功能。??getForObject()?
???getForEntity()?
???postForLocation()?
???postForObject()?
???put()?
???HttpMessageConverter?
???HttpMessageConverter?
?
public interface HttpMessageConverter{ // Indicates whether the given class can be read by this converter. boolean canRead(Class> clazz, MediaType mediaType); // Indicates whether the given class can be written by this converter. boolean canWrite(Class> clazz, MediaType mediaType); // Return the list of {@link MediaType} objects supported by this converter. List getSupportedMediaTypes(); // Read an object of the given type form the given input message, and returns it. T read(Class extends T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; // Write an given object to the given output message. void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException;}
框架中提供了主要媒體 (MIME) 類型的具體實現(xiàn)。
默認構(gòu)造函數(shù)為主要 MIME 類型注冊一組標準的消息轉(zhuǎn)換器。您還可以編寫自己的轉(zhuǎn)換器并通過屬性注冊。??RestTemplate?
???messageConverters?
?
向模板注冊的默認轉(zhuǎn)換器實例為 、、 和 。有關詳細信息,請參閱下表。??ByteArrayHttpMessageConverter?
???StringHttpMessageConverter?
???ResourceHttpMessageConverter?
???SourceHttpMessageConverter?
???AllEncompassingFormHttpMessageConverter?
?
表 2.1.默認消息轉(zhuǎn)換器
消息正文轉(zhuǎn)換器 | 收錄規(guī)則 |
ByteArrayHttpMessageConverter | 始終包括在內(nèi) |
StringHttpMessageConverter | |
ResourceHttpMessageConverter | |
SourceHttpMessageConverter | |
AllEncompassingFormHttpMessageConverter | |
SimpleXmlHttpMessageConverter | 如果存在簡單 XML 序列化程序,則包括在內(nèi)。 |
MappingJackson2HttpMessageConverter | 如果存在杰克遜 2.x JSON 處理器,則包括在內(nèi)。 |
GsonHttpMessageConverter | 如果 Gson 存在,則包括在內(nèi)。如果 Jackson 2.x 在類路徑上都可用,則 Gson 優(yōu)先于 Gson。 |
以下實現(xiàn)在 Spring for Android 中可用。對于所有轉(zhuǎn)換器,將使用默認媒體類型,但可以通過屬性重寫。??HttpMessageConverter?
???supportedMediaTypes?
?
可以從 HTTP 請求和響應讀取和寫入字節(jié)數(shù)組的實現(xiàn)。默認情況下,此轉(zhuǎn)換器支持所有媒體類型 (),并且寫入時為 .這可以通過設置支持的媒體類型屬性和重寫來覆蓋。??HttpMessageConverter?
???*/*?
???Content-Type?
???application/octet-stream?
???getContentType(byte[])?
?
可以從 HTTP 請求和響應讀取和寫入表單數(shù)據(jù)的實現(xiàn)。默認情況下,此轉(zhuǎn)換器讀取和寫入媒體類型。從 .??HttpMessageConverter?
???application/x-www-form-urlencoded?
???MultiValueMap
?
的擴展,添加了對基于 XML 和 JSON 的部分的支持。??FormHttpMessageConverter?
?
可以讀取和寫入資源的實現(xiàn)。默認情況下,此轉(zhuǎn)換器可以讀取所有媒體類型。寫入資源用于 。??HttpMessageConverter?
???Resource?
???application/octet-stream?
???Content-Type?
?
可以從 HTTP 請求和響應讀取和寫入的實現(xiàn)。僅支持 、 和。默認情況下,此轉(zhuǎn)換器支持 和 。??HttpMessageConverter?
???javax.xml.transform.Source?
???DOMSource?
???SAXSource?
???StreamSource?
???text/xml?
???application/xml?
?
可以從 HTTP 請求和響應讀取和寫入字符串的實現(xiàn)。默認情況下,此轉(zhuǎn)換器支持所有文本媒體類型 (),并使用 .??HttpMessageConverter?
???text/*?
???Content-Type?
???text/plain?
?
可以使用簡單框架的 HTTP 請求和響應讀取和寫入 XML 的實現(xiàn)。XML映射可以通過使用Simple提供的注釋根據(jù)需要進行自定義。當需要其他控件時,可以通過屬性注入自定義。默認情況下,此轉(zhuǎn)換器讀取和寫入媒體類型 、 和 。??HttpMessageConverter?
???Serializer?
???Serializer?
???Serializer?
???application/xml?
???text/xml?
???application/*+xml?
?
重要的是要注意,這不是與Spring OXM兼容的消息轉(zhuǎn)換器。它是一個獨立的實現(xiàn),通過 Spring for Android 實現(xiàn) XML 序列化。
將以下依賴項添加到類路徑中以啟用 .??SimpleXmlHttpMessageConverter?
?
格拉德爾:
dependencies { compile("org.simpleframework:simple-xml:${version}")}
專家:
org.simpleframework simple-xml ${simple-version}
可以使用杰克遜 (2.x)的 .JSON 映射可以根據(jù)需要通過使用 Jackson 提供的注釋進行自定義。當需要進一步控制時,對于需要為特定類型提供自定義 JSON 序列化程序/反序列化程序的情況,可以通過屬性注入自定義。默認情況下,此轉(zhuǎn)換器支持 .??HttpMessageConverter?
???ObjectMapper?
???ObjectMapper?
???ObjectMapper?
???application/json?
?
請注意,默認情況下,此消息轉(zhuǎn)換器和兩者都支持。因此,您應該只向?qū)嵗砑右粋€ JSON 消息轉(zhuǎn)換器。 將使用它找到的第一個與指定 MIME 類型匹配的轉(zhuǎn)換器,因此包括兩者可能會產(chǎn)生意外結(jié)果。??GsonHttpMessageConverter?
???application/json?
???RestTemplate?
???RestTemplate?
?
在類路徑中包含以下依賴項以啟用 .請注意,如果您手動將 jar 復制到項目中,則還需要包含 和 jar。??MappingJackson2HttpMessageConverter?
???jackson-annotations?
???jackson-core?
?
格拉德爾:
dependencies { compile("com.fasterxml.jackson.core:jackson-databind:${version}")}
專家:
com.fasterxml.jackson.core jackson-databind ${jackson-version}
可以使用 Google Gson 的類讀取和寫入 JSON 的實現(xiàn)。 JSON 映射可以根據(jù)需要通過使用??Gson??提供的注釋進行自定義。當需要進一步控制時,對于需要為特定類型提供自定義 JSON 序列化程序/反序列化程序的情況,可以通過屬性注入自定義。默認情況下,此轉(zhuǎn)換器支持 .??HttpMessageConverter?
???Gson?
???Gson?
???Gson?
???application/json?
?
請注意,默認情況下,此消息轉(zhuǎn)換器和兩者都支持。因此,您應該只向?qū)嵗砑右粋€ JSON 消息轉(zhuǎn)換器。 將使用它找到的第一個與指定 MIME 類型匹配的轉(zhuǎn)換器,因此包括兩者可能會產(chǎn)生意外結(jié)果。??MappingJackson2HttpMessageConverter?
???application/json?
???RestTemplate?
???RestTemplate?
?
在類路徑中包含以下依賴項以啟用 .??GsonHttpMessageConverter?
?
格拉德爾:
dependencies { compile("com.google.code.gson:gson:${version}")}
專家:
com.google.code.gson gson ${gson-version}
使用 ,很容易調(diào)用 RESTful API。下面是幾個使用示例,說明了發(fā)出 RESTful 請求的不同方法。??RestTemplate?
?
以下所有示例均基于示例 Android 應用程序。可以使用以下命令檢索示例應用的源代碼:
$ git clone git://github.com/spring-projects/spring-android-samples.git
以下示例顯示了對搜索詞“Spring Framework”的搜索向 google 的查詢。
String url = "https://ajax.googleapis.com/ajax/services/search/web?v=1.0&q={query}"; // Create a new RestTemplate instanceRestTemplate restTemplate = new RestTemplate();// Make the HTTP GET request, marshaling the response to a StringString result = restTemplate.getForObject(url, String.class, "Spring Framework");
Gzip 壓縮可以顯著減小 REST 請求中返回的響應數(shù)據(jù)的大小。Gzip 必須由向其發(fā)出請求的 Web 服務器支持。通過將標頭的內(nèi)容編碼類型設置為 ,您將請求服務器使用 gzip 壓縮進行響應。如果 gzip 可用或在服務器上啟用,則它應返回壓縮響應。RestTemplate 檢查響應中的標頭,以確定響應實際上是否經(jīng)過 gzip 壓縮。目前,RestTemplate 僅支持標頭中的 gzip 內(nèi)容編碼類型。如果響應數(shù)據(jù)被確定為 gzip 壓縮,則使用??GZIPInputStream?對其進行解壓縮。??Accept-Encoding?
???gzip?
???Content-Encoding?
???Content-Encoding?
?
以下示例演示如何從服務器請求 gzip 壓縮響應。
// Add the gzip Accept-Encoding headerHttpHeaders requestHeaders = new HttpHeaders();requestHeaders.setAcceptEncoding(ContentCodingType.GZIP);HttpEntity> requestEntity = new HttpEntity
需要注意的一點是,當將 J2SE 工具與 、Gingerbread 和更新版本一起使用時,會自動設置接受編碼標頭以請求 gzip 響應。這是較新版本的Android內(nèi)置功能。如果要禁用 gzip,則必須在標頭中設置值。??SimpleClientHttpRequestFactory?
???identity?
?
// Add the identity Accept-Encoding headerHttpHeaders requestHeaders = new HttpHeaders();requestHeaders.setAcceptEncoding(ContentCodingType.IDENTITY);HttpEntity> requestEntity = new HttpEntity
假設您已經(jīng)定義了一個 Java 對象,您希望從返回 JSON 內(nèi)容的 RESTful Web 請求中填充。封送處理 JSON 內(nèi)容需要 Jackson 或 Gson 在類路徑上可用。
根據(jù)從 RESTful 請求返回的 JSON 數(shù)據(jù)定義對象:
public class Event { private Long id; private String title; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public String setTitle(String title) { this.title = title; }}
發(fā)出 REST 請求:
// Create a new RestTemplate instanceRestTemplate restTemplate = new RestTemplate();// Make the HTTP GET request, marshaling the response from JSON to an array of EventsEvent[] events = restTemplate.getForObject(url, Event[].class);
您還可以設置請求的標頭:??Accept?
?
// Set the Accept headerHttpHeaders requestHeaders = new HttpHeaders();requestHeaders.setAccept(Collections.singletonList(new MediaType("application","json")));HttpEntity> requestEntity = new HttpEntity
使用我們之前定義的相同 Java 對象,我們可以修改檢索 XML 的請求。
根據(jù)從 RESTful 請求返回的 XML 數(shù)據(jù)定義對象。請注意 Simple 用于封送對象的注釋:
@Rootpublic class Event { @Element private Long id; @Element private String title; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public String setTitle(String title) { this.title = title; }}
若要從 xml 封送事件數(shù)組,需要為列表定義一個包裝類:
@Root(name="events")public class EventList { @ElementList(inline=true) private Listevents; public List getEvents() { return events; } public void setEvents(List events) { this.events = events; }}
發(fā)出 REST 請求:
// Create a new RestTemplate instanceRestTemplate restTemplate = new RestTemplate();// Make the HTTP GET request, marshaling the response from XML to an EventList objectEventList eventList = restTemplate.getForObject(url, EventList.class);
您還可以指定請求的標頭:??Accept?
?
// Set the Accept headerHttpHeaders requestHeaders = new HttpHeaders();requestHeaders.setAccept(Collections.singletonList(new MediaType("application","xml")));HttpEntity> requestEntity = new HttpEntity
將您定義的 Java 對象發(fā)布到接受 JSON 數(shù)據(jù)的 RESTful 服務。
根據(jù) RESTful 請求所需的 JSON 數(shù)據(jù)定義對象:
public class Message { private long id; private String subject; private String text; public void setId(long id) { this.id = id; } public long getId() { return id; } public void setSubject(String subject) { this.subject = subject; } public String getSubject() { return subject; } public void setText(String text) { this.text = text; } public String getText() { return text; }}
發(fā)出 REST 請求。在此示例中,請求以字符串值響應:
// Create and populate a simple object to be used in the requestMessage message = new Message();message.setId(555);message.setSubject("test subject");message.setText("test text");// Create a new RestTemplate instanceRestTemplate restTemplate = new RestTemplate();// Make the HTTP POST request, marshaling the request to JSON, and the response to a StringString response = restTemplate.postForObject(url, message, String.class);
您還可以在請求中指定標頭:??Content-Type?
?
// Create and populate a simple object to be used in the requestMessage message = new Message();message.setId(555);message.setSubject("test subject");message.setText("test text");// Set the Content-Type headerHttpHeaders requestHeaders = new HttpHeaders();requestHeaders.setContentType(new MediaType("application","json"));HttpEntityrequestEntity = new HttpEntity (message, requestHeaders);// Create a new RestTemplate instanceRestTemplate restTemplate = new RestTemplate();// Make the HTTP POST request, marshaling the request to JSON, and the response to a StringResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);String result = responseEntity.getBody();
此示例說明如何使用用戶名和密碼填充HTTP 基本身份驗證標頭。如果用戶名和密碼被接受,您將收到請求的響應。如果它們不被接受,則服務器應該返回HTTP 401未授權響應。在內(nèi)部,RestTemplate 處理響應,然后拋出 .通過調(diào)用此異常,可以確定確切原因并適當處理它。??HttpClientErrorException?
???getStatusCode()?
?
// Set the username and password for creating a Basic Auth requestHttpAuthentication authHeader = new HttpBasicAuthentication(username, password);HttpHeaders requestHeaders = new HttpHeaders();requestHeaders.setAuthorization(authHeader);HttpEntity> requestEntity = new HttpEntity
標簽: 構(gòu)造函數(shù) 應用程序 您還可以