標籤:
Spring之在用戶端訪問RESTful業務
RestTemplate 是用戶端訪問RESTful業務的核心類。在概念上與Spring其他的模板類相似,比如JdbcTemplate和JmsTemplate。RestTemplate的行為是可以定製的,通過提供回調方法和配置HttpMessageConverter(用於將對象打包到HTTP請求體中並從返回的響應中解壓為一個對象)。由於一般使用XML作為訊息格式,Spring提供了MarshallingHttpMessageConverter 使用對象到XML的架構,這是org.springframework.oxm包的一部分。這個給你了將XML映射為對象,提供了寬泛的選擇。
這節描述了如何使用RestTemplate和其關聯的HttpMessageConverters。
21.10.1 RestTemplate
Java中調用RESTful業務,一般使用一個輔助類,比如Apache的HttpComponents HttpClient。對於普通的REST操作,這種方式是非常低級的。
[java] view plaincopy
- String uri = "http://example.com/hotels/1/bookings";
-
- PostMethod post = new PostMethod(uri);
- String request = // create booking request content
- post.setRequestEntity(new StringRequestEntity(request));
-
- httpClient.executeMethod(post);
-
- if (HttpStatus.SC_CREATED == post.getStatusCode()) {
- Header location = post.getRequestHeader("Location");
- if (location != null) {
- System.out.println("Created new booking at :" + location.getValue());
- }
- }
RestTemplate提供了進階方法,對應著六個主要的HTTP方法,使得在一行中調用RESTful業務並執行REST最好的實踐。
注意:RestTemplate還有一個非同步部分。
RestTemplate 方法回顧表
HTTP方法 RestTemplate方法
DELETE delete
GET getForObjectgetForEntity
HEAD headForHeaders(String url,String。。。urlVariables)
OPTIONS optionsForAllow(String url,String。。。urlVariables)
POST postForLocation(String url,Object request,String。。。urlVariables) postForObeject(String url,Object request,Class<T> responseType,String...uriVariables)
PUT put(String url,Object reuqest,String...urlVariables)
PATCH and others exchange execute
RestTemplate方法的名字遵循一個命名規範,第一部分指定了調用什麼HTTP方法,第二部分指明了傳回值。例如,getForObject()方法執行一個GET,並將HTTP響應轉為你想要的物件類型並返回這個對象。postForLocation()方法執行一個POST操作,將給定的對象轉為一個HTTP請求並返回HTTP響應的location頭,這裡可以找到最新的對象。在處理HTTP請求的異常情形下,將拋出RestClientException異常類型;可以通過將ResponseErrorHandler實現插入到RestTemplate可以改變這種異常處理的行為。
exchange和execute方法是上述列表指定的方法的泛化版本並且支援其他的結合和方法,比如HTTP PATCH。然而,底層的HTTP也必須支援想得到的聯合。JDK的HttpURLConnection 不支援PATCH方法,但是了Apache HttpComponents HttpClient的4.2版本或者後面的會支援。它們也使得RestTemplate讀HTTP響應到一個一般的類型(比如List<Account>)),使用一個ParameterizedTypeReference,這是一個新類用來抓取和傳遞一般類型資訊。
傳遞給這些方法的對象和從這些方法返回的對象由HttpMessageConverter執行個體轉化和從訊息轉化。主要類型的轉換器是預設註冊的,但是了你也可以封裝你自己的轉換器並使用messageConverters()的bean屬性註冊。與這個模板註冊的預設轉換器執行個體是ByteArrayHttpMessageConverter,StringHttpMessageConverter,FormHttpMessageConverter和SourceHttpMessageConverter。你可以使用messageConverters()bean屬性重寫這些預設的,尤其是當使用MarshallingHttpMessageConverter或MappingJackson2HttpMessageConverter時重寫就是必須的了。
每個方法傳遞URI模板參數,用兩種方式,要不String變數長度參數,要不Map<String,String>. 例如:
[java] view plaincopy
- String result = restTemplate.getForObject(
- "http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42", "21");
上述使用的變數長度參數,
[java] view plaincopy
- 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提供了HttpComponentsClientHttpRequestFactory 工廠類,使用Apache HttpComponents HttpClient 建立請求。HttpComponentsClientHttpRequestFactory使用org.apache.http.client.HttpClient的執行個體配置,反過來使用認證資訊或者串連池功能配置。
注意:
java.net實現HTTP請求時,可能產生一個異常,當訪問響應狀態時,這代表了一個錯誤。如果這是一個問題,轉為使用HttpComponentsClientHttpRequestFactory
前面的例子使用Apache HttpComponents HttpClient直接重寫,並使用下面顯示的RestTemplate:
[java] view plaincopy
- uri = "http://example.com/hotels/{id}/bookings";
-
- RestTemplate template = new RestTemplate();
-
- Booking booking = // create booking object
-
- URI location = template.postForLocation(uri, booking, "1");
為使用Apache HttpComponents 而不是本地的java.net功能,構造如下的RestTemplate :
[java] view plaincopy
- RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());
注意:Apache HttpClient支援gzip編碼。為使用它,構造了HttpComponentsClientHttpRequestFactory工廠類,如下所示:
[java] view plaincopy
- HttpClient httpClient = HttpClientBuilder.create().build();
- ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
- RestTemplate restTemplate = new RestTemplate(requestFactory);
一般的回調介面是RequestCallback 併當調用執行方法時調用
[java] view plaincopy
- 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介面定義如下:
[java] view plaincopy
- public interface RequestCallback {
- void doWithRequest(ClientHttpRequest request) throws IOException;
- }
允許你操作要求標頭並寫到請求體中。當使用execute方法時,你不必擔心任何資源管理,模板將總是關閉請求並處理任何錯誤。
使用URI working with URI
對於每個主要的HTTP方法,RestTemplate提供了String類型的URI或者java.net.URI執行個體的變數作為第一個參數。
String URI變數接受模板參數作為一個String變數長度參數或者作為一個Map<String,String>。它們也假設URL String類型是不編碼的並且需要編碼。例子如下:
[java] view plaincopy
- restTemplate.getForObject("http://example.com/hotel list", String.class);
將在http://example.com/hotel%20list上執行一個GET請求。這意味著如果你輸入String類型的已經編碼的URL,其將再編碼一次。即http://example.com/hotel%20list將被變為http://example.com/hotel%2520list。如果這不是我們想要的結果,使用java.net.URI方法變數,其假設已經編碼的url是有用的,如果你想多次使用一個單一的URI。
UriComponentsBuilder這個類能用於構建和編碼URI,包括支援URI模板。例如,你可以以一個String類型的url開始。
[java] view plaincopy
- UriComponents uriComponents = UriComponentsBuilder.fromUriString(
- "http://example.com/hotels/{hotel}/bookings/{booking}").build()
- .expand("42", "21")
- .encode();
-
- URI uri = uriComponents.toUri();
或者分別指定每個URI組件:
[java] view plaincopy
- UriComponents uriComponents = UriComponentsBuilder.newInstance()
- .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build()
- .expand("42", "21")
- .encode();
-
- URI uri = uriComponents.toUri();
請求和回應標頭的處理
除了上述的方法外,RestTemplate也有exchange()方法,能用於基於HttpEntity類的任何HTTP方法的執行。
也許更加重要的是,exchange()這個方法可以用於添加請求和回應標頭。例如:
[java] view plaincopy
- HttpHeaders requestHeaders = new HttpHeaders();
- requestHeaders.set("MyRequestHeader", "MyValue");
- HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);
-
- HttpEntity<String> response = template.exchange(
- "http://example.com/hotels/{hotel}",
- HttpMethod.GET, requestEntity, String.class, "42");
-
- String responseHeader = response.getHeaders().getFirst("MyResponseHeader");
- String body = response.getBody();
在上述的例子中,我們首先準備了一個請求,其包含了MyRequestHeader頭資訊。稍後我們檢索了對應的響應,並讀了MyResponseHeader和訊息體。
Jackson JSON 視圖支援
可能指定一個Jackson JSON View序列化對象屬性子集。例如:
[java] view plaincopy
- JacksonSerializationValue jsv = new JacksonSerializationValue(new User("eric", "7!jd#h23"),
- User.WithoutPasswordView.class);
- HttpEntity<JacksonSerializationValue> entity = new HttpEntity<JacksonSerializationValue>(jsv);
- String s = template.postForObject("http://example.com/user", entity, String.class);
本文轉自:http://blog.csdn.net/luccs624061082/article/details/40893963
Spring之在用戶端訪問RESTful業務