跟随 Web Service 一路走来, 记忆中的 Apache SOAP, Apache Axis, XFire, 标准化的JAX-RPC, JAX-WS, 到后来半路杀出的的 Spring-WS, CXF
一切刚刚开始,一切望尘莫及,短命是纯技术的特征。
RPC 的平台局限性,SOAP 的类型 bind 的易脆性, JAX-WS 工具的信赖度, Spring-WS contract first 使一个小时可以完成(甚至在IDE中十分钟可以完成)的工作,要整一天,还要到看到 JUnit 的 Green bar 才算数。
已经标准化的JAX-RS,证明 RESTful 已经成为SOA加架的主流,以至于 Spring-WS 停止在了他的 1.59 版本,SpringSource 放弃了这个市场么?
呵呵!它早已意识到了问题的所在,市场上有多少 Spring-WS 的需求? 相比于它的 IoC, Spring-WS 是个失败的产品。它已经转移了重点:
2.5.6.1 Comprehensive REST support
Server-side support for building RESTful applications has been provided as an extension of the existing annotation driven MVC web framework. Client-side support is provided by the RestTemplate class in the spirit of other template classes such as JdbcTemplate and JmsTemplate. Both server and client side REST functionality make use of HttpConverters to facilitate the conversion between objects and their representation in HTTP requests and responses.
The MarshallingHttpMessageConverter uses the Object to XML mapping functionality mentioned earlier.
下面的代码 使用 RestTemplate 访问,SpringMVC 3 的一个 Controller (RESTful service),service 要求一个 SHA512 key.
RestTemplate 封装了一个 ClientHttpRequestFactory,Spring3 提供两种实现:
1. SimpleClientHttpRequestFactory 采用JDK URLConnection
2. CommonsClientHttpRequestFactory 采用 commons/httpclient 3.x (注意不是4)
- @SuppressWarnings("unchecked")
- private List<BufferedImage> searchProductImage(String keyword, String apikey, int page, int max) {
- final String restUri = "http://localhost:8080/hjpetstore/rest/products/{keyword}?apikey={apikey}&page={page}&max={max}";
- Source product = restTemplate.getForObject(restUri, Source.class, keyword, apikey, page, max);
- final String imageUrl = "http://localhost:8080/hjpetstore/images/{imageFileName}";
- List<BufferedImage> images = (List<BufferedImage>) xpathTemplate.evaluate("//image", product, new NodeMapper() {
- @Override
- public Object mapNode(Node node, int i) throws DOMException {
- //Element image = (Element) node;
- org.jdom.Element image = new DOMBuilder().build((Element) node);
- String imageFileName = image.getValue();
- //String imageFileName = image.getFirstChild().getNodeValue();
- return restTemplate.getForObject(imageUrl, BufferedImage.class, imageFileName);
- }
- });
- return images;
- }
逻辑的处理是 Xpath 解析 Response的XML,再次 请求 image 的url,然后利用 org.springframework.http.converter.BufferedImageHttpMessageConverter 返回一个 BufferedImage 的列表,送给 Swing 组件渲染出来。
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:util="http://www.springframework.org/schema/util"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
- http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
- <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
- <property name="locations">
- <list>
- <value>application.properties</value>
- </list>
- </property>
- </bean>
- <bean id="searchProductListRest" class="org.pprun.hjpetstore.client.SearchProductListRest">
- <constructor-arg ref="restTemplate"/>
- <constructor-arg ref="xpathTemplate"/>
- </bean>
- <!-- the template can be used to call home-grown or external RESTful service -->
- <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
- <property name="requestFactory">
- <bean class="org.springframework.http.client.CommonsClientHttpRequestFactory">
- <constructor-arg>
- <bean class="org.apache.commons.httpclient.HttpClient">
- <constructor-arg index="0">
- <bean id="httpClientParams" class="org.apache.commons.httpclient.params.HttpClientParams">
- <property name="authenticationPreemptive" value="true"/>
- </bean>
- </constructor-arg>
- <constructor-arg index="1">
- <bean class="org.apache.commons.httpclient.MultiThreadedHttpConnectionManager">
- <property name="params">
- <bean class="org.apache.commons.httpclient.params.HttpConnectionManagerParams">
- <property name="soTimeout" value="${rest.service.timeout}" />
- <property name="connectionTimeout" value="${rest.service.connectionTimeout}" />
- <property name="defaultMaxConnectionsPerHost" value="${rest.service.maxConnections}" />
- <property name="maxTotalConnections" value="${rest.service.maxTotalConnections}" />
- <property name="staleCheckingEnabled" value="${rest.service.staleCheckEnabled}" />
- </bean>
- </property>
- </bean>
- </constructor-arg>
- </bean>
- </constructor-arg>
- </bean>
- </property>
- <!-- 19.9.2 HTTP Message Conversion
- several main media type converters have been registered,
- but if we overwrite tihs property, we have to list all our need
- -->
- <property name="messageConverters">
- <list>
- <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
- <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter"/>
- </list>
- </property>
- </bean>
- <bean id="xpathTemplate" class="org.springframework.xml.xpath.Jaxp13XPathTemplate"/>
- </beans>