在文章中,我學習了spring-ws基本的知識,在文章最後我也實現一個簡單的項目,訪問能夠看到wsdl文件,可是我也遇到了一個問題,沒法經過soap UI的測試,通過這一段業餘時間的學習,這個問題解決。html
這是上一個學習建立的項目的demo演示連接,打開能夠看到生成的wsdl。java
上一次學習遇到的問題是,經過生成的wsdl在soap UI測試的時候,生成的請求參數和我要解析的參數不同,我認爲沒法解析,web
這是soap ui生成的請求數據spring
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:web="http://mycompany.com/hr/webservice"> <soapenv:Header/> <soapenv:Body> <web:HolidayRequest> <!--You may enter the following 2 items in any order--> <web:Holiday> <!--You may enter the following 2 items in any order--> <web:StartDate>2017-05-05</web:StartDate> <web:EndDate>2017-05-05</web:EndDate> </web:Holiday> <web:EmployeeType> <!--You may enter the following 3 items in any order--> <web:Number>147</web:Number> <web:FirstName>156</web:FirstName> <web:LastName>457</web:LastName> </web:EmployeeType> </web:HolidayRequest> </soapenv:Body> </soapenv:Envelope>
後臺解析的代碼:segmentfault
startDateExpression = xPathFactory.compile("//tns:StartDate", Filters.element(), null, namespace); endDateExpression = xPathFactory.compile("//tns:EndDate", Filters.element(), null, namespace); firstNameExpression = xPathFactory.compile("//tns:FirstName", Filters.element(), null, namespace); lastNameExpression = xPathFactory.compile("//tns:LastName", Filters.element(), null, namespace);
我認爲沒法解析是由於兩邊的表達式不同,沒法解析對應的字段,但是通過最近一段學習,發現不少wsdl都不是對應,可是仍然能夠正常提供服務,因而我無論兩邊不同的問題,使用soap ui 測試一下,結果確實接收到了請求,測試結果:app
請求進來了 Booking holiday for [Fri May 05 00:00:00 CST 2017-Fri May 05 00:00:00 CST 2017] for [156 457]
從結果上看,數據都取出來。dom
另外這裏有個事情須要解釋一下:eclipse
xsd修改了,再也不和上一篇文章中的內容徹底同樣,這是修改後的文件:webapp
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://mycompany.com/hr/webservice" elementFormDefault="qualified" targetNamespace="http://mycompany.com/hr/webservice"> <xs:element name="HolidayRequest"> <xs:complexType> <xs:all> <xs:element name="Holiday" type="tns:Holiday"/> <xs:element name="EmployeeType" type="tns:Employee"/> </xs:all> </xs:complexType> </xs:element> <xs:complexType name="Holiday"> <xs:all> <xs:element name="StartDate" type="xs:string"/> <xs:element name="EndDate" type="xs:string"/> </xs:all> </xs:complexType> <xs:complexType name="Employee"> <xs:all> <xs:element name="Number" type="xs:integer"/> <xs:element name="FirstName" type="xs:string"/> <xs:element name="LastName" type="xs:string"/> </xs:all> </xs:complexType> </xs:schema>
不知道有沒有奇怪人我爲何,我把前綴改爲了【tns】,緣由是這樣的,當我把前綴改爲【hr】時:ide
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:hr="http://mycompany.com/hr/webservice" elementFormDefault="qualified" targetNamespace="http://mycompany.com/hr/webservice"> <xs:element name="HolidayRequest"> <xs:complexType> <xs:all> <xs:element name="Holiday" type="hr:Holiday"/> <xs:element name="EmployeeType" type="hr:Employee"/> </xs:all> </xs:complexType> </xs:element> <xs:complexType name="Holiday"> <xs:all> <xs:element name="StartDate" type="xs:string"/> <xs:element name="EndDate" type="xs:string"/> </xs:all> </xs:complexType> <xs:complexType name="Employee"> <xs:all> <xs:element name="Number" type="xs:integer"/> <xs:element name="FirstName" type="xs:string"/> <xs:element name="LastName" type="xs:string"/> </xs:all> </xs:complexType> </xs:schema>
而後重啓項目生成wsdl,結果以下:
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:sch="http://mycompany.com/hr/webservice" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://mycompany.com/hr/webservice" targetNamespace="http://mycompany.com/hr/webservice"> <wsdl:types> <xs:schema xmlns:hr="http://mycompany.com/hr/webservice" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://mycompany.com/hr/webservice"> <xs:element name="HolidayRequest"> <xs:complexType> <xs:all> <xs:element name="Holiday" type="hr:Holiday"/> <xs:element name="EmployeeType" type="hr:Employee"/> </xs:all> </xs:complexType> </xs:element> <xs:complexType name="Holiday"> 還有不少
能夠看到,生成的wsdl頭部中仍然是:
xmlns:tns="http://mycompany.com/hr/webservice" targetNamespace="http://mycompany.com/hr/webservice"
我查看了一下源碼,在設置namespace的代碼中:
@Override public void afterPropertiesSet() throws WSDLException { Assert.notNull(getTargetNamespace(), "'targetNamespace' is required"); WSDLFactory wsdlFactory = WSDLFactory.newInstance(); Definition definition = wsdlFactory.newDefinition(); definition.setTargetNamespace(getTargetNamespace()); definition.addNamespace(TARGET_NAMESPACE_PREFIX, getTargetNamespace()); if (importsProvider != null) { importsProvider.addImports(definition); } if (typesProvider != null) { typesProvider.addTypes(definition); } if (messagesProvider != null) { messagesProvider.addMessages(definition); } if (portTypesProvider != null) { portTypesProvider.addPortTypes(definition); } if (bindingsProvider != null) { bindingsProvider.addBindings(definition); } if (servicesProvider != null) { servicesProvider.addServices(definition); } setDefinition(definition); }
其中使用一個名爲TARGET_NAMESPACE_PREFIX的常量做爲前綴,在類中定義以下:
public static final String TARGET_NAMESPACE_PREFIX = "tns";
也就是說,若是你採用的是生成wsdl,而不是本身寫的wsdl的話,本身定義的命名空間都是tns前綴,
因此,我也就改爲tns了,反正寫什麼都沒什麼用,最終都是tns。
spring-ws推薦第一次生成以後,採用靜態配置的方式訪問wsdl文件,因而新建了一個webservicelearn2項目。
把上一篇文章生成的wsdl文件另存爲orders.wsdl,放到web-inf下面,web.xml沒有改,pom.xml文件也沒有修改,只有spring-ws配置文件改爲了下面這個樣子:
<?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:oxm="http://www.springframework.org/schema/oxm" xmlns:sws="http://www.springframework.org/schema/web-services" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd http://www.springframework.org/schema/web-services http://www.springframework.org/schema/web-services/web-services.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <sws:static-wsdl id="orders" location="/WEB-INF/orders.wsdl"/> </beans>
按照文檔說明,此時訪問http://localhost:8089/webserv...就能夠訪問了。
在這期間,項目clean了一下,從新下載jar包,而後項目就一直出錯,啓動項目時老是報500錯誤:
java.lang.ClassNotFoundException: javax.wsdl.extensions.ExtensibilityElement at java.net.URLClassLoader.findClass(URLClassLoader.java:381) at org.eclipse.jetty.webapp.WebAppClassLoader.findClass(WebAppClassLoader.java:550) at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:475) at org.eclipse.jetty.webapp.WebAppClassLoader.loadClass(WebAppClassLoader.java:428) at org.springframework.ws.wsdl.wsdl11.DefaultWsdl11Definition.<init>(DefaultWsdl11Definition.java:56) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
我知道這是缺jar,缺的是wsdlj jar包,可是spring-ws官方參考文檔上說並不須要這個jar,這是官方參考文檔
其中關於依賴的配置以下:
<dependencies> <dependency> <groupId>org.springframework.ws</groupId> <artifactId>spring-ws-core</artifactId> <version></version> </dependency> <dependency> <groupId>jdom</groupId> <artifactId>jdom</artifactId> <version>2.0.1</version> </dependency> <dependency> <groupId>jaxen</groupId> <artifactId>jaxen</artifactId> <version>1.1</version> </dependency> </dependencies>
我一直覺得,個人項目哪裏出錯了,由於開始的項目是對的,只不太重新下載jar就出錯了,確定是我哪裏改錯了,就這個問題,還諮詢了jetbrains idea的技術才支持,最後才發現,spring-ws-core的版本問題形成的;
這是2.1.4版本:
這是最新版本:
也就是說新版本,須要在pom.xml配置wsdlj才能使用,至於爲何剛開始是對的,我也沒想明白。
到此爲止,動態生成也好,靜態wsdl也好,都能正常訪問,有些東西,看着簡單,本身搞起來,老是出錯,因此仍是要多動手。