快人一步
VMware 提供培訓和認證,為您的進步注入強勁動力。
瞭解更多經過近一年的開發,我很高興地宣佈 Spring Web Services 2.0 已釋出!在這篇文章中,我想介紹一些主要的新特性。
您可能知道,我們將物件 XML 對映 (OXM) 模組從 Spring-WS 專案移到了 Spring 3.0 中。因此,由於 org.springframework.oxm 包中存在衝突的類,將 Spring-WS 1.5(及其自己的 OXM 模組)與 Spring 3.0 一起使用會有些問題。
從 2.0 版本開始,我們不再將 OXM 模組作為 Spring-WS 的一部分發布,而是依賴於 Spring 的 OXM。因此,為了正常工作,Spring Web Services 2.0 要求使用 Spring 3.0。通常,我們對版本要求會更寬鬆一些,不一定要求最新的 Spring 版本,但這是唯一能讓一切正常工作的方式。
由於依賴 Spring 3.0,我們也**要求使用 Java 5+**,並且整個程式碼庫都使用了 Java 5 的特性(如泛型、可變引數和列舉)。例如,與 XPathTemplate 結合使用的 NodeMapper 介面現在是泛型的,因此不再需要進行強制型別轉換
Person person = template.evaluateAsObject("//person", new DOMSource(document), new NodeMapper<Person>() {
public Person mapNode(Node node, int nodeNum) throws DOMException {
Element personElement = (Element) node;
return new Person(personElement.getAttribute("firstName"), personElement.getAttribute("lastName"));
}
});
請注意,即使我們升級了程式碼庫以使用 Java 5+ 特性,我們仍然以向後相容的方式進行。因此,Spring Web Services 2.0 向後相容 1.5。不過,我們確實移除了已棄用的類。例如,XsdBasedSoap11Wsdl4jDefinitionBuilder 已被 DefaultWsdl11Definition 取代,後者具有相同的功能,但更具可定製性。
Spring Web Services 2.0 中最重要的一個新特性是能夠在 @Endpoint 方法中使用任意引數型別。相對於 Spring-WS 1.5 的 @Endpoint 模型,一個巨大的改進是您現在可以混合和匹配引數,並且對返回型別的限制也更少。基本上,這使得 Spring-WS 的 @Endpoint 程式設計模型與 Spring 3 的 @Controller 模型旗鼓相當。
例如,您可以擁有以下 @Endpoint 方法
@PayloadRoot(localPart = "myRequest", namespace = "http://example.com")
@ResponsePayload
public MyJaxb2Response handleMyRequest(@RequestPayload org.w3c.dom.Element myElement,
SoapHeader requestHeader,
MessageContext messageContext) {
// do something interesting here
}
此方法將接收任何載荷根元素具有 "http://example.com" 名稱空間和 "myRequest" 本地名稱的 SOAP 訊息。然後,此載荷將作為 W3C DOM 元素傳遞,並結合 SoapHeader(用於訪問單個頭元素)和整個訊息上下文。
當前支援的引數/返回型別包括
要將請求訊息的載荷獲取為這些引數型別中的任何一種,您需要使用 @RequestPayload 註解引數。類似地,如果您希望返回值最終成為響應訊息的載荷,您需要使用 @ResponsePayload 註解方法。這與 Spring 3 的 @Controller 模型非常相似,Spring 3 中有 @RequestBody 和 @ResponseBody,它們在 HTTP 領域提供了類似的功能。
此外,我們支援以下不帶 @RequestPayload 的引數型別
@Namespaces(@Namespace(prefix = "tns", uri = "http://springframework.org/spring-ws"))
public void myEndpointMethod(@XPathParam("/tns:root")String s) {
// do something slightly more interesting here
}
這些名稱空間註解(@Namespace 和 @Namespaces)可以出現在方法、類或包級別(即 package-info.java)上。
要啟用此程式設計模型,您只需在 Spring Web Services 應用程式上下文中放置 <sws:annotation-driven/> 即可
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sws="http://www.springframework.org/schema/web-services"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services-2.0.xsd">
<sws:annotation-driven/>
<!-- other beans go here, or perhaps a <context:component-scan/> -->
</beans>
您可以選擇為此元素提供 marshaller 和 unmarshaller 屬性,分別指向一個 OXM Marshaller 和 Unmarshaller。這將啟用支援使用此 marshaller 支援的型別作為 @RequestPayload/@ResponsePayload 型別。
請注意,我們也已棄用對 <sws:marshalling-endpoints/> 和 <sws:xpath-endpoints/> 的支援,轉而支援 <sws:annotation-driven/>。因此,這兩個元素在 XSD 模式的 2.0 版本中不存在,但在 1.5 版本中仍然存在。所以您可以選擇繼續使用模式的 1.5 版本,或者升級到 2.0 並使用 <sws:annotation-driven/>。
最後,與 Spring 中的所有內容一樣,引數/返回型別機制是完全可插拔的。因此,如果您沒有看到您想要的引數型別,請隨時編寫您自己的 MethodArgumentResolver 或 MethodReturnValueHandler,將其插入 Spring-WS,然後就可以使用了!
另一個主要新特性是新的 Web 服務整合測試模組 spring-ws-test。此模組包含測試客戶端(即使用 WebServiceTemplate 的類)和伺服器(即 @Endpoints)的功能。客戶端和伺服器端測試模組都提供了“流暢”的 API,因此您通常可以在 IDE 中使用程式碼補全功能(即 ctrl-space)來指導您設定測試過程。
測試客戶端程式碼的典型場景包括
例如,考慮這個 Web 服務客戶端類
import org.springframework.ws.client.core.support.WebServiceGatewaySupport;
public class CustomerClient extends WebServiceGatewaySupport {
public int getCustomerCount() {
CustomerCountRequest request = new CustomerCountRequest();
request.setCustomerName("John Doe");
CustomerCountResponse response =
(CustomerCountResponse) getWebServiceTemplate().marshalSendAndReceive(request);
return response.getCustomerCount();
}
}
CustomerClient 的典型測試如下所示
import javax.xml.transform.Source;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.xml.transform.StringSource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.assertEquals;
import org.springframework.ws.test.client.MockWebServiceServer;
import static org.springframework.ws.test.client.RequestMatchers.*;
import static org.springframework.ws.test.client.ResponseCreators.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("integration-test.xml")
public class CustomerClientIntegrationTest {
@Autowired
private CustomerClient client;
private MockWebServiceServer mockServer;
@Before
public void createServer() throws Exception {
mockServer = MockWebServiceServer.createServer(client);
}
@Test
public void customerClient() throws Exception {
Source requestPayload = new StringSource(
"<customerCountRequest xmlns='http://springframework.org/spring-ws'>" +
"<customerName>John Doe</customerName>" +
"</customerCountRequest>");
Source responsePayload = new StringSource(
"<customerCountResponse xmlns='http://springframework.org/spring-ws'>" +
"<customerCount>10</customerCount>" +
"</customerCountResponse>");
mockServer.expect(payload(requestPayload)).andRespond(withPayload(responsePayload));
int result = client.getCustomerCount();
assertEquals(10, result);
mockServer.verify();
}
}
有關客戶端測試的更多資訊,請參考參考手冊。
進行伺服器端整合測試的核心類是 MockWebServiceClient。其基本思想是此客戶端建立一個請求訊息,然後將其傳送到在標準 MessageDispatcherServlet 應用程式上下文中配置的端點。這些端點將處理訊息並建立響應。然後客戶端接收此響應,並根據已註冊的預期對其進行驗證。
MockWebServiceClient 的典型用法是
例如,考慮這個簡單的 Web 服務端點類
@Endpoint
public class CustomerEndpoint {
@ResponsePayload
public CustomerCountResponse getCustomerCount(
@RequestPayload CustomerCountRequest request) {
CustomerCountResponse response = new CustomerCountResponse();
response.setCustomerCount(10);
return response;
}
}
CustomerEndpoint 的典型測試如下所示
import javax.xml.transform.Source;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.xml.transform.StringSource;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.ws.test.server.MockWebServiceClient;
import static org.springframework.ws.test.server.RequestCreators.*;
import static org.springframework.ws.test.server.ResponseMatchers.*;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("spring-ws-servlet.xml")
public class CustomerEndpointIntegrationTest {
@Autowired
private ApplicationContext applicationContext;
private MockWebServiceClient mockClient;
@Before
public void createClient() {
mockClient = MockWebServiceClient.createClient(applicationContext);
}
@Test
public void customerEndpoint() throws Exception {
Source requestPayload = new StringSource(
"<customerCountRequest xmlns='http://springframework.org/spring-ws'>" +
"<customerName>John Doe</customerName>" +
"</customerCountRequest>");
Source responsePayload = new StringSource(
"<customerCountResponse xmlns='http://springframework.org/spring-ws'>" +
"<customerCount>10</customerCount>" +
"</customerCountResponse>");
mockClient.sendRequest(withPayload(requestPayload)).
andExpect(payload(responsePayload));
}
}
有關伺服器端測試的更多資訊,請參考參考手冊。
如果你想嘗試 Spring Web Services 2.0,可以訪問站點,或直接前往下載頁。如果你使用 Maven,升級應該很簡單,只需新增以下倉庫
<repository>
<id>spring-release</id>
<name>Spring Release Repository</name>
<url>http://maven.springframework.org/release</url>
</repository>
然後可以像這樣新增單個依賴項
<dependency>
<groupId>org.springframework.ws</groupId>
<artifactId>spring-ws-core</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
這些 jar 應該很快就會在 Maven Central 上可用。
最後,我要感謝 Lukáš Křečan 和 Tareq Abed Rabbo。這兩位社群成員在此版本的開發過程中提供了重要幫助。