Spring之在客户端访问RESTful业务

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在CODE上查看代码片派生到我的代码片
 
  1. String uri = "http://example.com/hotels/1/bookings";  
  2.   
  3. PostMethod post = new PostMethod(uri);  
  4. String request = // create booking request content  
  5. post.setRequestEntity(new StringRequestEntity(request));  
  6.   
  7. httpClient.executeMethod(post);  
  8.   
  9. if (HttpStatus.SC_CREATED == post.getStatusCode()) {  
  10.     Header location = post.getRequestHeader("Location");  
  11.     if (location != null) {  
  12.         System.out.println("Created new booking at :" + location.getValue());  
  13.     }  
  14. }  

 

 

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在CODE上查看代码片派生到我的代码片
 
  1. String result = restTemplate.getForObject(  
  2.         "http://example.com/hotels/{hotel}/bookings/{booking}", String.class,"42", "21");  

 

 

 

上述使用的变量长度参数,

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. Map<String, String> vars = Collections.singletonMap("hotel", "42");  
  2. String result = restTemplate.getForObject(  
  3.         "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在CODE上查看代码片派生到我的代码片
 
  1. uri = "http://example.com/hotels/{id}/bookings";  
  2.   
  3. RestTemplate template = new RestTemplate();  
  4.   
  5. Booking booking = // create booking object  
  6.   
  7. URI location = template.postForLocation(uri, booking, "1");  


为使用Apache HttpComponents 而不是本地的java.net功能,构造如下的RestTemplate :

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. RestTemplate template = new RestTemplate(new HttpComponentsClientHttpRequestFactory());  


注意:Apache HttpClient支持gzip编码。为使用它,构造了HttpComponentsClientHttpRequestFactory工厂类,如下所示:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. HttpClient httpClient = HttpClientBuilder.create().build();  
  2. ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);  
  3. RestTemplate restTemplate = new RestTemplate(requestFactory);  

 

 


一般的回调接口是RequestCallback 并当调用执行方法时调用

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public <T> T execute(String url, HttpMethod method, RequestCallback requestCallback,  
  2.         ResponseExtractor<T> responseExtractor, String... urlVariables)  
  3.   
  4. // also has an overload with urlVariables as a Map<String, String>.  


 

 

 

RequestCallback接口定义如下:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. public interface RequestCallback {  
  2.  void doWithRequest(ClientHttpRequest request) throws IOException;  
  3. }  

允许你操作请求头并写到请求体中。当使用execute方法时,你不必担心任何资源管理,模板将总是关闭请求并处理任何错误。

 

 

 

 

使用URI working with URI

 

对于每个主要的HTTP方法,RestTemplate提供了String类型的URI或者java.net.URI实例的变量作为第一个参数。

 

String URI变量接受模板参数作为一个String变量长度参数或者作为一个Map<String,String>。它们也假设URL String类型是不编码的并且需要编码。例子如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. 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在CODE上查看代码片派生到我的代码片
 
  1. UriComponents uriComponents = UriComponentsBuilder.fromUriString(  
  2.         "http://example.com/hotels/{hotel}/bookings/{booking}").build()  
  3.         .expand("42", "21")  
  4.         .encode();  
  5.   
  6. URI uri = uriComponents.toUri();  

 

 

或者分别指定每个URI组件:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. UriComponents uriComponents = UriComponentsBuilder.newInstance()  
  2.         .scheme("http").host("example.com").path("/hotels/{hotel}/bookings/{booking}").build()  
  3.         .expand("42", "21")  
  4.         .encode();  
  5.   
  6. URI uri = uriComponents.toUri();  

 

 

请求和响应头的处理

 

除了上述的方法外,RestTemplate也有exchange()方法,能用于基于HttpEntity类的任何HTTP方法的执行。

 

也许更加重要的是,exchange()这个方法可以用于添加请求和响应头。例如:

 

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. HttpHeaders requestHeaders = new HttpHeaders();  
  2. requestHeaders.set("MyRequestHeader", "MyValue");  
  3. HttpEntity<?> requestEntity = new HttpEntity(requestHeaders);  
  4.   
  5. HttpEntity<String> response = template.exchange(  
  6.         "http://example.com/hotels/{hotel}",  
  7.         HttpMethod.GET, requestEntity, String.class, "42");  
  8.   
  9. String responseHeader = response.getHeaders().getFirst("MyResponseHeader");  
  10. String body = response.getBody();  

 


在上述的例子中,我们首先准备了一个请求,其包含了MyRequestHeader头信息。稍后我们检索了对应的响应,并读了MyResponseHeader和消息体。

 

Jackson JSON 视图支持

可能指定一个Jackson JSON View序列化对象属性子集。例如:

 

[java] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. JacksonSerializationValue jsv = new JacksonSerializationValue(new User("eric", "7!jd#h23"),  
  2.     User.WithoutPasswordView.class);  
  3. HttpEntity<JacksonSerializationValue> entity = new HttpEntity<JacksonSerializationValue>(jsv);  
  4. String s = template.postForObject("http://example.com/user", entity, String.class);  

 

本文转自:http://blog.csdn.net/luccs624061082/article/details/40893963

posted @ 2015-07-08 17:44  Rozdy  阅读(904)  评论(0编辑  收藏  举报