Spring Web Services 2.0 發布

工程 | Arjen Poutsma | 2011 年 1 月 11 日 | ...

經過將近一年的努力,我很榮幸地宣布 Spring Web Services 2.0 已經發布!在這篇文章中,我想概述一些主要的新功能。

需要 Java 5+ 和 Spring 3.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,後者具有相同的功能,但更具可自訂性。

改進的 @Endpoint 程式設計模型

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
}

此方法將接收任何 SOAP 訊息,其中酬載根元素具有「http://example.com」命名空間和「myRequest」本機名稱。然後,此酬載將作為 W3C DOM 元素傳遞,並結合 SoapHeader (以存取個別標頭元素) 和整個訊息內容。

目前支援的參數/回傳類型包括

  • DOM 元素 (預設為 W3C DOM;如果類別路徑中存在 JDOM、dom4j、XOM,則會自動啟用)
  • OXM Marshaller 支援的類型 (需要明確設定的 marshaller)
  • JAXB2 類型,如果 JAXB2 在類別路徑中找到 (這表示您不再需要明確設定 Jaxb2Marshaller)
  • javax.xml.transform.Source 和子類型
  • StAX XMLStreamReader 和 XMLEventreaders。請注意,這些只能用作參數類型,不能用作回傳類型。

若要取得請求訊息的酬載作為任何這些參數類型,您必須使用 @RequestPayload 註釋參數。同樣地,如果您希望回傳值最終出現在回應訊息的酬載中,則必須使用 @ResponsePayload 註釋方法。這與 Spring 3 的 @Controller 模型非常相似,在 HTTP 空間中,我們有 @RequestBody 和 @ResponseBody,它們提供類似的功能。

此外,我們支援以下不含 @RequestPayload 的參數類型

  • MessageContext
  • SoapHeader、SoapBody、SoapEvelope (請求訊息的)
  • @XPathParam 參數。請注意,您現在可以使用 @Namespace 和 @Namespaces 註釋來指定 XPath 表達式中使用的任何命名空間,而不再需要在 XML 應用程式內容中設定它們。例如
    
    @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/>。因此,這兩個元素在 2.0 版的 XSD 結構描述中不存在,但在 1.5 版的結構描述中仍然存在。因此,您可以堅持使用 1.5 版的結構描述,或升級到 2.0 和 <sws:annotation-driven/>。

最後,與 Spring 中的所有內容一樣,參數/回傳類型機制是完全可插拔的。因此,如果您沒有看到您想要看到的參數類型,請隨時編寫您自己的 MethodArgumentResolver 或 MethodReturnValueHandler,將其插入 Spring-WS,您就完成了!

新的整合測試模組

另一個主要的新功能是新的 Web 服務整合測試模組 spring-ws-test。此模組包含用於測試用戶端 (即使用 WebServiceTemplate 的類別) 和伺服器 (即 @Endpoints) 的功能。用戶端和伺服器端測試模組都提供「流暢」API,因此您通常可以使用 IDE 中的程式碼完成功能 (即 ctrl-space) 來引導您完成設定測試的過程。

用戶端整合測試

用於執行用戶端整合測試的核心類別是 MockWebServiceServer。底層概念是 Web 服務範本連線到此模擬伺服器,將請求訊息傳送給它,模擬伺服器然後根據已註冊的預期驗證請求訊息。如果符合預期,模擬伺服器然後準備回應訊息,將其傳送回範本。

測試用戶端程式碼的典型情境包括

  1. 建立 MockWebServiceServer。
  2. 設定有關請求訊息的預期。
  3. 建立適當的回應訊息
  4. 正常使用 WebServiceTemplate,可以直接使用或透過用戶端程式碼使用。
  5. 呼叫 MockWebServiceServer.verify() 以確保已滿足所有預期。

例如,考慮此 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 的典型用法是

  1. 建立 MockWebServiceClient 執行個體。
  2. 傳送請求訊息。
  3. 設定回應預期。

例如,考慮這個簡單的 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 引入了對 Spring Security 3.0 的支援
  • 對 XMPP (Jabber) 傳輸的支援

更多資訊

如果您想試用 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。這兩位社群成員在此版本的開發過程中提供了很大的幫助。

取得 Spring 電子報

隨時掌握 Spring 電子報的最新資訊

訂閱

搶先一步

VMware 提供訓練和認證,以加速您的進展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位檔。

了解更多

即將到來的活動

查看 Spring 社群中所有即將到來的活動。

查看全部