javascript
spring创建web项目_使用Spring WS创建合同优先的Web服务
spring創(chuàng)建web項(xiàng)目
1引言
本文介紹了如何使用來實(shí)現(xiàn)和測(cè)試SOAP Web服務(wù)
Spring Web Services項(xiàng)目 。 本示例將JAXB2用于(取消)編組。 為了開發(fā)服務(wù),我將使用合同優(yōu)先的方法,該方法首先定義服務(wù)合同,然后基于此合同實(shí)施服務(wù)。
本文分為以下幾節(jié):
- 2解釋申請(qǐng)
- 3實(shí)施服務(wù)
- 3.1創(chuàng)建合同
- 3.2生成Java類
- 3.3實(shí)現(xiàn)SOAP端點(diǎn)
- 3.4配置應(yīng)用程序
- 4測(cè)試服務(wù)
- 5附加信息
- 5.1實(shí)施客戶
- 5.2內(nèi)部運(yùn)作方式
2解釋申請(qǐng)
示例應(yīng)用程序處理訂單。 我們有一個(gè)前端控制器(messageDispatcher servlet),它將處理訂單請(qǐng)求,調(diào)用服務(wù)以處理訂單并返回結(jié)果。
您可以在github上獲取源代碼。
3實(shí)施服務(wù)
3.1創(chuàng)建合同
由于我們將使用“合同優(yōu)先”方法,因此創(chuàng)建合同的最簡(jiǎn)單方法是首先定義示例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,這是一個(gè)開放源代碼工具,將允許我們從xml文檔中生成xsd模式。 我已經(jīng)將該庫包含到項(xiàng)目構(gòu)建路徑中(可以從Trang 網(wǎng)站獲得此jar),并且創(chuàng)建了一個(gè)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)。 由于模式是自動(dòng)生成的,因此我們可能需要進(jìn)行一些修改以使其適應(yīng)我們的需求。 讓我們來看看:
客戶端請(qǐ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)添加不同的驗(yàn)證,但是在本示例中,我將只修改幾種類型,例如clientId,productId和ConfirmationId(xs:string)和orderDate(xs:date)。 XML數(shù)據(jù)類型到Java類型的映射由JAXB完成。 您可以檢查提供了哪些映射
在這里 。
為了完成該架構(gòu),我們將把response元素復(fù)制到請(qǐng)求架構(gòu)中。 我創(chuàng)建了帶有響應(yīng)和請(qǐng)求的第三個(gè)架構(gòu):
客戶端服務(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文件表示。 如果您不想手動(dòng)創(chuàng)建它,Spring-ws項(xiàng)目為我們提供了一種從XSD模式生成此文件的方法。 您將在配置應(yīng)用程序部分中看到第二種方法。
3.2生成Java類
我們將使用JAXB2生成請(qǐng)求和響應(yīng)對(duì)象。 JAXB的XJC編譯器將負(fù)責(zé)從我們之前生成的XSD架構(gòu)轉(zhuǎn)換這些對(duì)象。 它將作為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類(您可能需要刷新項(xiàng)目)。
3.3實(shí)現(xiàn)SOAP端點(diǎn)
端點(diǎn)接收未編組的消息有效負(fù)載,并使用此數(shù)據(jù)來調(diào)用訂單服務(wù)。 然后它將返回服務(wù)響應(yīng),該響應(yīng)將由端點(diǎn)適配器編組:
@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 }這是端點(diǎn)使用的注釋的簡(jiǎn)短描述:
@Endpoint :將類注冊(cè)為組件。 這樣,將通過組件掃描檢測(cè)到該類。
@PayloadRoot :將端點(diǎn)方法注冊(cè)為請(qǐng)求的處理程序。 該注釋將定義該方法可以處理的請(qǐng)求消息類型。 在我們的示例中,它將接收消息,其中其有效負(fù)載根元素具有與我們創(chuàng)建的XSD架構(gòu)中定義的名稱空間相同的名稱空間,并且其本地名稱是為請(qǐng)求定義的名稱(clientDataRequest)。
@RequestPayload :指示要作為參數(shù)傳遞給方法的請(qǐng)求消息的有效負(fù)載。
@ResponsePayload ,指示將返回值用作響應(yīng)消息的有效負(fù)載。
3.4配置應(yīng)用程序
web.xml
應(yīng)用程序配置(如數(shù)據(jù)源,transactionManager等)
加載應(yīng)用程序上下文
<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>這是一個(gè)Servlet,它將充當(dāng)處理所有SOAP調(diào)用的前端控制器。 它的功能是將傳入的XML消息派生到端點(diǎn),就像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。
在動(dòng)態(tài)wsdl中,在locationUri屬性中輸入什么值都沒有關(guān)系,因?yàn)樗鼘⒂蒑essageDispatcherServlet處理。 因此,wsdl將在以下位置可用:
http:// localhost:8081 / spring-ws / orders / whatever / orderDefinition.wsdl
4測(cè)試服務(wù)
下面的示例創(chuàng)建一個(gè)模擬客戶端,該客戶端將訪問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));} }此測(cè)試中使用的配置文件非常簡(jiǎn)單,僅包含對(duì)服務(wù)組件的掃描:
<context:component-scan base-package="xpadro.spring.ws"/> <ws:annotation-driven/>5附加信息
5.1實(shí)施客戶
為了方便客戶端訪問Web服務(wù),Spring為我們提供了WebServiceTemplate類。 此類包含用于發(fā)送和接收消息的方法,并且還使用轉(zhuǎn)換器對(duì)(取消)編組對(duì)象。
我創(chuàng)建了一個(gè)充當(dāng)服務(wù)客戶端的測(cè)試:
@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());} }配置測(cè)試文件包含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í)行此測(cè)試之前使用已部署的Web服務(wù)應(yīng)用程序啟動(dòng)服務(wù)器即可。
5.2內(nèi)部運(yùn)作方式
如果您只想實(shí)現(xiàn)Web服務(wù),那么上一節(jié)將結(jié)束本文。 對(duì)于那些對(duì)它如何真正起作用感到好奇的人,我將嘗試解釋如何將請(qǐng)求映射到端點(diǎn),這比到目前為止的解釋要低一些。
當(dāng)請(qǐng)求到達(dá)MessageDispatcher時(shí),它依賴于兩個(gè)組件:
端點(diǎn)映射
MessageDispatcher包含一個(gè)端點(diǎn)映射列表,每個(gè)端點(diǎn)映射都包含一個(gè)先前注冊(cè)的方法端點(diǎn)的映射。 在我們的例子中,JAXB映射PayloadRootAnnotationMethodEndpointMapping已注冊(cè)所有帶有@PayloadRoot注釋的方法。 如果消息的有效負(fù)載的合格名稱解析為注冊(cè)方法,則它將被返回給MessageDispatcher。 如果我們不注釋我們的方法,它將無法處理請(qǐng)求。
端點(diǎn)適配器
然后,MessageDispatcher將詢問其每個(gè)端點(diǎn)適配器是否支持當(dāng)前請(qǐng)求。 在我們的情況下,適配器檢查以下兩個(gè)條件是否都成立:
- 傳遞給該方法的至少一個(gè)參數(shù)使用@RequestPayload進(jìn)行注釋
- 如果端點(diǎn)方法返回響應(yīng),則必須使用@ResponsePayload進(jìn)行注釋
如果返回了適配器,則它將調(diào)用端點(diǎn),在將參數(shù)傳遞給方法之前將其解組。 當(dāng)該方法返回響應(yīng)時(shí),適配器將封送它。
下圖是此步驟的簡(jiǎn)化版本,以簡(jiǎn)化操作:
結(jié)論
我們已經(jīng)看到了有關(guān)如何實(shí)現(xiàn)簡(jiǎn)單的Web服務(wù)然后對(duì)其進(jìn)行測(cè)試的介紹。 如果您有興趣,還可以看看如何使用MockWebServiceServer 測(cè)試客戶端。
參考: 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
spring創(chuàng)建web項(xiàng)目
總結(jié)
以上是生活随笔為你收集整理的spring创建web项目_使用Spring WS创建合同优先的Web服务的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Data Redis:Se
- 下一篇: 使用@JsonIdentityInfo的