服務使用CXF框架客戶端使用Axis2框架的webservice實現方案
背景:
執行在兩臺獨立伺服器上的兩個web服務,其中一個web服務需要訪問另一個web服務的業務方法。但是兩個服務各自的執行環境不同,一個服務執行在jdk1.5上(服務端),使用spring2.5.6框架管理bean,而另一個執行在jdk1.4環境下(客戶端)。現在要求通過webservice技術讓客戶端能訪問服務端提供的webservice服務。
方案:
服務端因為使用了spring,故使用Apache CXF框架將業務bean的方法釋出為webservice服務 ,客戶端使用支援jdk1.4的Axis2-1.4.1,生成服務端業務方法的客戶端存根,提供客戶端使用。
備註:此方案對保證服務安全尚未有良好解決方案,對安全有要求請不要參考!
環境
IDE:Eclipse3.5
程式碼生成工具:axis2-eclipse-codegen-wizard.zip和axis2-eclipse-service-archiver-wizard.zip,下載地址http://apache.justdn.org/ws/axis2/tools/1_4_1/
服務端:
釋出一個webservice服務,
1.jar包 ,參考如下圖片
2.實體類Person.java
3.服務類和介面定義
介面 PersonService.java
類PersonServiceImpl.java
4.bean配置
5.cxf配置檔案
applicationContext-cxf.xml
<?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:jaxws="http://cxf.apache.org/jaxws "
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws
http://cxf.apache.org/schemas/jaxws.xsd "
default-autowire="byName" default-lazy-init="true">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<bean id="jaxWsServiceFactoryBean" class="org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean" scope="prototype">
<property name="wrapped" value="true"/>
<property name="dataBinding" ref="aegisBean"/>
<property name="serviceConfigurations">
<list>
<bean class="org.apache.cxf.jaxws.support.JaxWsServiceConfiguration"/>
<bean class="org.apache.cxf.aegis.databinding.AegisServiceConfiguration"/>
<bean class="org.apache.cxf.service.factory.DefaultServiceConfiguration"/>
</list>
</property>
</bean>
<bean id="aegisBean" class="org.apache.cxf.aegis.databinding.AegisDatabinding"/>
<jaxws:endpoint id="WSpersonService" implementor="#personService" address="/PersonService">
<jaxws:serviceFactory>
<ref bean="jaxWsServiceFactoryBean"/>
</jaxws:serviceFactory>
</jaxws:endpoint>
</beans>
4.web.xml配置CXFServlet
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance " xmlns="http://java.sun.com/xml/ns/javaee " xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd " xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd " id="WebApp_ID" version="2.5">
<display-name>CXFService</display-name>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext*.xml</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<servlet>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
5.測試服務端
點選連結進入,可以檢視服務的wsdl
至此服務釋出成功!
客戶端:(這裡客戶端只用java工程進行測試,web工程同理)
1.建立一個java project 命名為CxfServiceClient(如果需要在jdk1.4下執行,請將編譯級別改為jdk1.4,否則忽略)
2.生成客戶端程式碼
按照以下操作步驟進行:
選擇Axis2 Code Generator,將PersonService的wsdl地址拷貝到以下輸入框:
選擇如下的引數:
繼續點選Next,進入如下視窗,選擇客戶端工程根路徑為程式碼生成路徑,選擇Axis2的lib匯入到客戶端工程(可選的步驟):
最後finish:
如果生成程式碼報錯,請在外掛中lib下加入stax-api-1.0.1.jar和backport-util-concurrent-3.1.jar,檢查plugin.xml是否配置這兩項,然後重啟eclipse
程式碼生成完畢,這時會發現程式碼上有錯誤提示,原因是axis2的jar包還沒有引入,將CxfServiceClient/lib下的jar包引入classpath即可解決此錯誤。
可以發現,針對List的資料型別,Axis2實際上是生成了ArrayOfPerson的類,將List轉換成了物件陣列進行處理!
3.寫測試用例執行測試
在生成的測試程式碼上完善測試邏輯,將生成的test包拖拽到src下,完成兩個測試方法的程式碼,示例:
執行測試,報錯,
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at test.com.webservice.service.impl.PersonServiceImplServiceTest.getTestObject(PersonServiceImplServiceTest.java:130)
at test.com.webservice.service.impl.PersonServiceImplServiceTest.testsave(PersonServiceImplServiceTest.java:74)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at junit.framework.TestCase.runTest(TestCase.java:164)
at junit.framework.TestCase.runBare(TestCase.java:130)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:120)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.ExceptionInInitializerError
at com.webservice.service.impl.SaveDocument$Factory.newInstance(SaveDocument.java:45)
... 22 more
Caused by: java.lang.RuntimeException: Cannot load SchemaTypeSystem. Unable to load class with name schemaorg_apache_xmlbeans.system.s5EA05717581B4DB0D124E78F071F0690.TypeSystemHolder. Make sure the generated binary files are on the classpath.
at org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader(XmlBeans.java:783)
at com.webservice.service.impl.SaveDocument.<clinit>(SaveDocument.java:20)
... 23 more
Caused by: java.lang.ClassNotFoundException: schemaorg_apache_xmlbeans.system.s5EA05717581B4DB0D124E78F071F0690.TypeSystemHolder
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader(XmlBeans.java:769)
... 24 more
解決方案 :將生成的CxfServiceClient/resources/schemaorg_apache_xmlbeans拷貝到class編譯路徑下,我這裡是bin目錄下,如圖,
再執行,提示成功!