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来支持