cxf 解析調用外部soap類型的webservice

使用cxf的wsdl2java調用外部webservice提供的wsdl的步驟,使用過程中的問題與注意事項也做了相關總結。


一、可用的請求wsdl的webservice路徑

服務器提供一個外部可調用的webservice的wsdl路徑,在瀏覽器中可直接反問道wsdl文件,在soapUI中可測試每個請求的有效的路徑(該webservice是已發佈可工外部調用的有效請求)


二、下載配置Apache CXF提供的生成Client的工具

1.下載:

 http://cxf.apache.org/download.html官網 下載apache-cxf-3.0.10.zip(或者別的壓縮包,建議使用較新的工具包),將下載到的zip解壓到本地某個文件下,如我解壓到D盤的tool文件夾下

2.配置環境變量:

將cxf所在路徑配置到環境變量中,如CXF_HOME=D:\tools\apache-cxf-3.0.10,在Path變量中添加;%CXF_HOME%\bin(講cxf的bin目錄配置到path中)。

運行cmd dos命令,輸入wsdl2java -v,輸出爲wsdl2java - Apache CXF 3.0.10這種版本信息表示安裝配置成功,否則則可能安裝失敗


三、使用wsdl2java的命令生成客戶端代碼

1,簡單使用命令生成代碼到某目錄下:

可在本地手動切換到需要生成代碼的目錄下,在路徑中輸入cmd回車即轉到該目錄下——》wsdl2java  -p '包名'  -encoding UTF-8 https://XXX.XX.XXXService?wsdl 回車即可生成

-p 生成代碼放置的包,命令中建議加上,方便直接放到項目目錄下,默認的包可能不符java包的命名規則(如可能生成以java、org等包)

-encoding 建議加上,不指定編碼可能導致生成的文件產生編碼衝突的錯誤而無法直接使用

-autoNameResolution當有兩個或者多個wsdl需要生成到同一個目錄下時,再次運行命令行需加入此參數,如果wsdl中有相似相同的方法名或者引用了相同名稱的類會提示“具有相同名稱 "XXXX" 的類/接口已在使用。請使用類定製設置來解決此衝突。”,無法正常生成,在wsdl2java的命令中加上這段標示,標示每個wsdl生成類時都會生成一個唯一的Number,讓同名的類也可生成。注意事項或出現ObjectFactory的錯誤時參考下面使用難點中的2即可解決。

四、使用難點

注意1:cxf所依賴的包比較坑爹,包引用的版本不對會出現非常多的問題

(ws的插件可以使用比較新的版本)

<plugin>
                <groupId>org.jvnet.jax-ws-commons</groupId>
                <artifactId>jaxws-maven-plugin</artifactId>
                <version>2.3.1-b03</version>
                <dependencies>
                    <dependency>
                        <groupId>javax.xml</groupId>
                        <artifactId>webservices-api</artifactId>
                        <version>2.0</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <sourceDestDir>${project.build.directory}/generated-sources/jaxws-wsimport</sourceDestDir>
                    <xnocompile>true</xnocompile>
                    <verbose>true</verbose>
                    <extension>true</extension>
                    <catalog>${basedir}/src/jax-ws-catalog.xml</catalog>
                </configuration>

            </plugin>

cxf的jar包依賴的版本如果出現問題會導致各種奇怪的報錯:(因爲cxf2.3.3所依賴的cxf-rt-frontend-jaxws、cxf-rt-transports-http-jetty都是2.2以上,如果這兩個包是2.1hi報錯)

 <cxf.version>2.2.3</cxf.version>

 <!--cxf -->     
        <!-- https://mvnrepository.com/artifact/org.apache.cxf/cxf -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf</artifactId>
            <version>2.3.3</version>
            <type>pom</type>
        </dependency>

        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-frontend-jaxws</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http</artifactId>
            <version>${cxf.version}</version>
        </dependency>
        <!-- Jetty is needed if you're are not using the CXFServlet -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>${cxf.version}</version>
        </dependency>

jaxb-api使用的版本也不可過高

 <!-- jaxb-api -->
        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.2.12</version>
        </dependency>:


注意2:ObjectFactory conflicts

生成多個wsdl文檔代碼時,-autoNameResolution解決ObjectFactory類名稱相同產生衝突時,會導致生成的ObjectFactory中只存在後執行生成命令的wsdl
的相關節點與方法,當再次調用之前生成的方法時,會報錯說XXX,XX.XXService?wsdl 無法調用的錯,簡單的解決方式是講之間生成的ObjectFactory的相關節
點與方法在被覆蓋掉的ObjectFactory中粘貼一遍即可

參照解決方法:http://www.codeproject.com/Tips/145051/Apache-CXF-wsdl-java-Error


注意3:The lifecycle method [finalizeConfig] must not throw a checked exception

當想要在應用中調用service來完成相關邏輯,如果直接調用會報錯類似The lifecycle method [finalizeConfig] must not throw a checked exception的錯誤,是因爲在依賴中加入了   <!-- Jetty is needed if you're are not using the CXFServlet -->
        <dependency>
            <groupId>org.apache.cxf</groupId>
            <artifactId>cxf-rt-transports-http-jetty</artifactId>
            <version>${cxf.version}</version>
        </dependency>

當使用main函數或者junit測試代碼時可以加上這段,但調用時不可加入這段依賴

問題參考:https://issues.apache.org/jira/browse/CXF-5483


注意4:javax.xml.ws.WebServiceException: Unsupported endpoint address的錯誤

解決方法是在service中加入endpoint的設置或者在port中設置Provider的endpoint參數

參見:http://tugdualgrall.blogspot.jp/2009/02/jax-ws-how-to-configure-service-end_17.html

注意5:...can`t create a instance of XXX

http://stackoverflow.com/questions/7415659/instantiationexception-during-jaxb-unmarshalling-abstract-base-class-with-xml


五、成功案例

通過三生成的service可直接調用(XXXservice的註解爲@WebServiceClient,註釋中各種需要的參數都是已經生成的)

XXXService service=new XXXService(XXX.Service.WSDL_LOCATION);//WSDL_LOCATION是生成的類中已經賦值的路徑http://XXX.XXX.XXService?wsdl

XXXPortType port=service.getXXXEndpoint();

//如果請求的wsdl有Bisic Authentication的認證,需要加下面這段

((BindingProvider) port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, "username");
((BindingProvider) port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, "password");
//然後直接調用port中的方法,即可拿到數據

port.getCaptcha().getImagePath().getValue();


---------------------案例中使用的是wso2提供的的webservice

wsdl:

https://ids-dev.zhishinet.com:9443/services/UserInformationRecoveryService?wsdl

https://ids-dev.zhishinet.com:9443/services/RemoteUserStoreManagerService?wsdl

用戶:admin

密碼:admin

忘記密碼:
getUserList("
http://wso2.org/claims/mobile",18666666666,null)
有用戶名,驗證驗證碼
VerificationBean ver = user.verifyUser(userName, null);
VerificationBean ver2 = user.sendRecoveryNotification(userName, ver.key, "");
VerificationBean ver3 = user.verifyConfirmationCode(userName, ver2.notificationData.notificationCode, null);
VerificationBean ver4 = user.updatePassword(userName, ver3.key, password);

修改密碼: 

updateCredential 






發佈了35 篇原創文章 · 獲贊 12 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章