javascript
使用Spring WS创建合同优先的Web服务
1引言
本文介紹了如何使用來實現(xiàn)和測試SOAP Web服務(wù)
Spring Web Services項目 。 本示例使用JAXB2進行(取消)編組。 為了開發(fā)服務(wù),我將使用合同優(yōu)先的方法,該方法首先定義服務(wù)合同,然后基于該合同實施服務(wù)。
本文分為以下幾節(jié):
- 2解釋申請
- 3實施服務(wù)
- 3.1創(chuàng)建合同
- 3.2生成Java類
- 3.3實現(xiàn)SOAP端點
- 3.4配置應(yīng)用程序
- 4測試服務(wù)
- 5附加信息
- 5.1實施客戶
- 5.2內(nèi)部運作方式
2解釋申請
示例應(yīng)用程序處理訂單。 我們有一個前端控制器(messageDispatcher servlet),它將處理訂單請求,調(diào)用服務(wù)以處理訂單并返回結(jié)果。
您可以在github上獲取源代碼。
3實施服務(wù)
3.1創(chuàng)建合同
由于我們將使用合同優(yōu)先的方法,因此創(chuàng)建合同的最簡單方法是首先定義示例xml文檔,然后我們將使用工具生成合同。 以下是示例xml文檔:
client-request.xml
<clientDataRequest xmlns="http://www.xpadro.spring.samples.com/orders"clientId="A-123"productId="C5FH"quantity="5" />client-response.xml
<clientDataResponse xmlns="http://www.xpadro.spring.samples.com/orders" confirmationId="7890B"orderDate="2013-09-22"amount="15.50" />為了創(chuàng)建模式,我們可以使用Trang,這是一個開放源代碼工具,將允許我們從xml文檔中生成xsd模式。 我已經(jīng)將該庫包含到項目構(gòu)建路徑中(可以從Trang 網(wǎng)站獲得此jar),并且我已經(jīng)創(chuàng)建了一個Ant任務(wù)來執(zhí)行轉(zhuǎn)換:
generate-schema.xml
<project name="Ant-Generate-Schema-With-Trang" default="generate" basedir="."><property name="src.dir" location="src" /><property name="trang.dir" location="lib" /><property name="source.dir" location="${src.dir}/main/webapp/WEB-INF/schemas/samples" /><property name="schema.dir" location="${src.dir}/main/webapp/WEB-INF/schemas/xsd" /><target name="generate" description="generates order schema"><delete dir="${schema.dir}" /><mkdir dir="${schema.dir}" /><java jar="${trang.dir}/trang.jar" fork="true"><arg value="${source.dir}/client-request.xml" /><arg value="${schema.dir}/client-request.xsd" /></java><java jar="${trang.dir}/trang.jar" fork="true"><arg value="${source.dir}/client-response.xml" /><arg value="${schema.dir}/client-response.xsd" /></java></target> </project>一旦執(zhí)行了Ant任務(wù),它將生成架構(gòu)。 由于模式是自動生成的,因此我們可能需要進行一些修改以使其適應(yīng)我們的需求。 讓我們來看看:
客戶端請求
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.xpadro.spring.samples.com/orders" xmlns:orders="http://www.xpadro.spring.samples.com/orders"><xs:element name="clientDataRequest"><xs:complexType><xs:attribute name="clientId" use="required" type="xs:NCName"/><xs:attribute name="productId" use="required" type="xs:NCName"/><xs:attribute name="quantity" use="required" type="xs:integer"/></xs:complexType></xs:element> </xs:schema>客戶端響應(yīng)
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.xpadro.spring.samples.com/orders" xmlns:orders="http://www.xpadro.spring.samples.com/orders"><xs:element name="clientDataResponse"><xs:complexType><xs:attribute name="amount" use="required" type="xs:decimal"/><xs:attribute name="confirmationId" use="required" type="xs:NMTOKEN"/><xs:attribute name="orderDate" use="required" type="xs:NMTOKEN"/></xs:complexType></xs:element> </xs:schema> 我們可以向這些架構(gòu)添加不同的驗證,但是在本示例中,我將僅修改幾種類型,例如clientId,productId和ConfirmationId(xs:string)和orderDate(xs:date)。 XML數(shù)據(jù)類型到Java類型的映射是由JAXB完成的。 您可以檢查提供了哪些映射
在這里 。
為了完成該架構(gòu),我們將把response元素復(fù)制到請求架構(gòu)中。 我用響應(yīng)和請求創(chuàng)建了第三個模式:
客戶端服務(wù)
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"elementFormDefault="qualified" targetNamespace="http://www.xpadro.spring.samples.com/orders"xmlns:orders="http://www.xpadro.spring.samples.com/orders"><xs:element name="clientDataRequest"><xs:complexType><xs:attribute name="clientId" use="required" type="xs:string" /><xs:attribute name="productId" use="required" type="xs:string" /><xs:attribute name="quantity" use="required" type="xs:integer" /></xs:complexType></xs:element><xs:element name="clientDataResponse"><xs:complexType><xs:attribute name="amount" use="required" type="xs:decimal" /><xs:attribute name="confirmationId" use="required" type="xs:string" /><xs:attribute name="orderDate" use="required" type="xs:date" /></xs:complexType></xs:element> </xs:schema>最后一步是寫合同,通常用WSDL文件表示。 如果您不想手動創(chuàng)建它,Spring-ws項目為我們提供了一種從XSD模式生成此文件的方法。 您將在配置應(yīng)用程序部分中看到第二種方法。
3.2生成Java類
我們將使用JAXB2生成請求和響應(yīng)對象。 JAXB的XJC編譯器將負責(zé)從我們之前生成的XSD架構(gòu)轉(zhuǎn)換這些對象。 它將作為Ant任務(wù)執(zhí)行:
<project name="Ant-Generate-Classes-With-JAXB2" default="generate" basedir="."><property name="src.dir" location="src" /><property name="java.dir" location="src/main/java" /><property name="schema.dir" location="${src.dir}/main/webapp/WEB-INF/schemas/xsd" /><target name="generate"><exec executable="xjc"><arg line=" -d ${java.dir} -p xpadro.spring.ws.types ${schema.dir}/client-service.xsd" /></exec></target> </project>該任務(wù)將在xpadro.spring.ws.types包中創(chuàng)建Java類(您可能需要刷新項目)。
3.3實現(xiàn)SOAP端點
端點接收未編組的消息有效負載,并使用此數(shù)據(jù)來調(diào)用訂單服務(wù)。 然后它將返回服務(wù)響應(yīng),該響應(yīng)將由端點適配器編組:
@Endpoint public class OrderEndpoint {@Autowiredprivate OrderService orderService;@PayloadRoot(localPart="clientDataRequest", namespace="http://www.xpadro.spring.samples.com/orders")public @ResponsePayload ClientDataResponse order(@RequestPayload ClientDataRequest orderData) {OrderConfirmation confirmation = orderService.order(orderData.getClientId(), orderData.getProductId(), orderData.getQuantity().intValue());ClientDataResponse response = new ClientDataResponse();response.setConfirmationId(confirmation.getConfirmationId());BigDecimal amount = new BigDecimal(Float.toString(confirmation.getAmount()));response.setAmount(amount);response.setOrderDate(convertDate(confirmation.getOrderDate()));return response;}//date conversion }這是端點使用的注釋的簡短描述:
@Endpoint :將類注冊為組件。 這樣,將通過組件掃描檢測到該類。
@PayloadRoot :將端點方法注冊為請求的處理程序。 該注釋將定義該方法可以處理的請求消息類型。 在我們的示例中,它將接收消息,其中其有效負載根元素具有與我們創(chuàng)建的XSD架構(gòu)中定義的名稱空間相同的名稱空間,并且其本地名稱是為請求定義的名稱(clientDataRequest)。
@RequestPayload :指示請求消息的有效負載作為參數(shù)傳遞給方法。
@ResponsePayload ,指示將返回值用作響應(yīng)消息的有效負載。
3.4配置應(yīng)用程序
web.xml
應(yīng)用程序配置(如數(shù)據(jù)源,transactionManager…)
加載應(yīng)用程序上下文
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>這是一個Servlet,它將充當(dāng)處理所有SOAP調(diào)用的前端控制器。 它的功能是將傳入的XML消息派生到端點,就像Spring MVC的DispatcherServlet一樣。
<servlet><servlet-name>orders</servlet-name><servlet-class>org.springframework.ws.transport.http.MessageDispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:xpadro/spring/ws/config/servlet-config.xml</param-value></init-param><load-on-startup>1</load-on-startup> </servlet><servlet-mapping><servlet-name>orders</servlet-name><url-pattern>/orders/*</url-pattern> </servlet-mapping> servlet-config.xml
此配置包含Web服務(wù)基礎(chǔ)結(jié)構(gòu)bean。
在動態(tài)wsdl中,將什么值放在locationUri屬性中都沒有關(guān)系,因為它將由MessageDispatcherServlet處理。 因此,wsdl將在以下位置可用:
http:// localhost:8081 / spring-ws / orders / whatever / orderDefinition.wsdl
4測試服務(wù)
下面的示例創(chuàng)建一個模擬客戶端,該客戶端將訪問Web服務(wù):
@ContextConfiguration("classpath:xpadro/spring/ws/test/config/test-server-config.xml") @RunWith(SpringJUnit4ClassRunner.class) public class TestWebService {@AutowiredApplicationContext context;private MockWebServiceClient mockClient;@Testpublic void testValidOrderRequest() {Source requestPayload = new StringSource("<clientDataRequest xmlns='http://www.xpadro.spring.samples.com/orders' " +"clientId='123' productId='XA-55' quantity='5'/>");Source responsePayload = new StringSource("<clientDataResponse xmlns='http://www.xpadro.spring.samples.com/orders' " +"amount='55.99' confirmationId='GHKG34L' orderDate='2013-10-26+02:00'/>");RequestCreator creator = RequestCreators.withPayload(requestPayload);mockClient = MockWebServiceClient.createClient(context);mockClient.sendRequest(creator).andExpect(ResponseMatchers.payload(responsePayload));}@Testpublic void testInvalidOrderRequest() {Source requestPayload = new StringSource("<clientDataRequest xmlns='http://www.xpadro.spring.samples.com/orders' " +"clientId='456' productId='XA-55' quantity='5'/>");Source responsePayload = new StringSource("<SOAP-ENV:Fault xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>" +"<faultcode>SOAP-ENV:Server</faultcode><faultstring xml:lang='en'>Client [456] not found</faultstring></SOAP-ENV:Fault>");RequestCreator creator = RequestCreators.withPayload(requestPayload);mockClient = MockWebServiceClient.createClient(context);mockClient.sendRequest(creator).andExpect(ResponseMatchers.payload(responsePayload));} }此測試中使用的配置文件非常簡單,僅包含對服務(wù)組件的掃描:
<context:component-scan base-package="xpadro.spring.ws"/> <ws:annotation-driven/>5附加信息
5.1實施客戶
為了方便客戶端訪問Web服務(wù),Spring為我們提供了WebServiceTemplate類。 此類包含用于發(fā)送和接收消息的方法,并且它還使用轉(zhuǎn)換器對(取消)編組對象。
我創(chuàng)建了一個充當(dāng)服務(wù)客戶端的測試:
@ContextConfiguration("classpath:xpadro/spring/ws/test/config/client-config.xml") @RunWith(SpringJUnit4ClassRunner.class) public class TestClient {@Autowired WebServiceTemplate wsTemplate;@Testpublic void invokeOrderService() throws Exception {ClientDataRequest request = new ClientDataRequest();request.setClientId("123");request.setProductId("XA-55");request.setQuantity(new BigInteger("5", 10));ClientDataResponse response = (ClientDataResponse) wsTemplate.marshalSendAndReceive(request);assertNotNull(response);assertEquals(new BigDecimal("55.99"), response.getAmount());assertEquals("GHKG34L", response.getConfirmationId());} }配置測試文件包含WebServiceTemplate配置:
<oxm:jaxb2-marshaller id="marshaller" contextPath="xpadro.spring.ws.types"/><bean class="org.springframework.ws.client.core.WebServiceTemplate"><property name="marshaller" ref="marshaller" /><property name="unmarshaller" ref="marshaller" /><property name="defaultUri" value="http://localhost:8081/spring-ws/orders" /> </bean>只需記住在執(zhí)行此測試之前使用已部署的Web服務(wù)應(yīng)用程序啟動服務(wù)器即可。
5.2內(nèi)部運作方式
如果您只想實現(xiàn)Web服務(wù),則本文在上一節(jié)中完成。 對于那些對它如何真正起作用感到好奇的人,我將嘗試解釋如何將請求映射到端點,這比到目前為止的解釋要低一些。
當(dāng)請求到達MessageDispatcher時,它依賴于兩個組件:
端點映射
MessageDispatcher包含一個端點映射列表,每個映射都包含一個先前注冊的方法端點的映射。 在我們的例子中,JAXB映射PayloadRootAnnotationMethodEndpointMapping已注冊所有帶有@PayloadRoot注釋的方法。 如果消息的有效負載的合格名稱解析為注冊方法,則它將被返回給MessageDispatcher。 如果我們不注釋我們的方法,它將無法處理請求。
端點適配器
然后,MessageDispatcher將詢問其每個端點適配器是否支持當(dāng)前請求。 在我們的情況下,適配器檢查以下條件是否都成立:
- 傳遞給該方法的至少一個參數(shù)使用@RequestPayload進行注釋
- 如果端點方法返回響應(yīng),則必須使用@ResponsePayload進行注釋
如果返回了適配器,則它將調(diào)用端點,在將參數(shù)傳遞給方法之前先將其解組。 當(dāng)該方法返回響應(yīng)時,適配器將封送它。
下圖是此步驟的簡化版本,以簡化操作:
結(jié)論
我們已經(jīng)看到了有關(guān)如何實現(xiàn)簡單的Web服務(wù)然后對其進行測試的介紹。 如果您有興趣,還可以看看如何使用MockWebServiceServer 測試客戶端。
參考: XavierPadró的博客博客中的JCG合作伙伴 Xavier Padro 使用Spring WS創(chuàng)建了合同優(yōu)先的Web服務(wù) 。翻譯自: https://www.javacodegeeks.com/2014/02/creating-contract-first-web-services-with-spring-ws.html
總結(jié)
以上是生活随笔為你收集整理的使用Spring WS创建合同优先的Web服务的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信安卓32位版本下载(微信安卓3)
- 下一篇: linux换行符号(linux >