利用cxf 开发 WebService

现在的项目中需要用到SOA概念的地方越来越多,最近我接手的一个项目中就提出了这样的业务要求,需要在.net开发的客户端系统中访问java开发的web系统,这样的业务需求自然需要通过WebService进行信息数据的操作。下面就将我们在开发中摸索的一点经验教训总结以下,以供大家参考.

在WebService开发笔记 2 -- VS 2005 访问WebServcie更简单中作一个跨平台访问WebServcie服务的例子....

在WebService开发笔记 3 -- 增强访问 WebService 的安全性通过一个简单的用户口令验证机制来加强一下WebService的安全性....

我们项目的整个架构使用的比较流行的WSH MVC组合,即webwork2 + Spring + Hibernate;
1.首先集成Apacha CXF WebService 到 Spring 框架中;
   apache cxf 下载地址:http://people.apache.org/dist/incubator/cxf/2.0.4-incubator/apache-cxf-2.0.4-incubator.zip
  在spring context配置文件中引入以下cxf配置
Xml代码

   1. <import resource="classpath*:META-INF/cxf/cxf.xml" /> 
   2. <import resource="classpath*:META-INF/cxf/cxf-extension-soap.xml" /> 
   3. <import resource="classpath*:META-INF/cxf/cxf-servlet.xml" /> 

<import resource="classpath*:META-INF/cxf/cxf.xml" />
<import resource="classpath*:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath*:META-INF/cxf/cxf-servlet.xml" />


   在web.xml中添加过滤器:
Xml代码

   1. <servlet> 
   2.     <servlet-name>CXFServlet</servlet-name> 
   3.     <servlet-class> 
   4.         org.apache.cxf.transport.servlet.CXFServlet 
   5.     </servlet-class> 
   6. </servlet> 
   7. <servlet-mapping> 
   8.     <servlet-name>CXFServlet</servlet-name> 
   9.     <url-pattern>/services/*</url-pattern> 
  10. </servlet-mapping> 

<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>



2.开发服务端WebService接口:
Java代码

   1. /**
   2.  * WebService接口定义类.
   3.  * 
   4.  * 使用@WebService将接口中的所有方法输出为Web Service.
   5.  * 可用annotation对设置方法、参数和返回值在WSDL中的定义.
   6.  */ 
   7. @WebService 
   8. public interface WebServiceSample { 
   9.  
  10.  
  11.     /**
  12.      * 一个简单的方法,返回一个字符串
  13.      * @param hello
  14.      * @return
  15.      */ 
  16.     String say(String hello); 
  17.      
  18.     /**
  19.      * 稍微复杂一些的方法,传递一个对象给服务端处理
  20.      * @param user
  21.      * @return
  22.      */ 
  23.     String sayUserName( 
  24.             @WebParam(name = "user")  
  25.             UserDTO user); 
  26.      
  27.     /**
  28.      * 最复杂的方法,返回一个List封装的对象集合
  29.      * @return
  30.      */ 
  31.     public  
  32.     @WebResult(partName="o") 
  33.     ListObject findUsers(); 
  34.  
  35. } 

/**
* WebService接口定义类.
*
* 使用@WebService将接口中的所有方法输出为Web Service.
* 可用annotation对设置方法、参数和返回值在WSDL中的定义.
*/
@WebService
public interface WebServiceSample {


/**
* 一个简单的方法,返回一个字符串
* @param hello
* @return
*/
String say(String hello);

/**
* 稍微复杂一些的方法,传递一个对象给服务端处理
* @param user
* @return
*/
String sayUserName(
@WebParam(name = "user")
UserDTO user);

/**
* 最复杂的方法,返回一个List封装的对象集合
* @return
*/
public
@WebResult(partName="o")
ListObject findUsers();

}


由简单到复杂定义了三个接口,模拟业务需求;

3.实现接口
Java代码

   1. /**
   2.  * WebService实现类.
   3.  * 
   4.  * 使用@WebService指向Interface定义类即可.
   5.  */ 
   6. @WebService(endpointInterface = "cn.org.coral.biz.examples.webservice.WebServiceSample") 
   7. public class WebServiceSampleImpl implements WebServiceSample { 
   8.  
   9.     public String sayUserName(UserDTO user) { 
  10.         return "hello "+user.getName(); 
  11.     } 
  12.  
  13.     public String say(String hello) { 
  14.         return "hello "+hello; 
  15.     } 
  16.  
  17.     public ListObject findUsers() { 
  18.         ArrayList<Object> list = new ArrayList<Object>(); 
  19.          
  20.         list.add(instancUser(1,"lib")); 
  21.         list.add(instancUser(2,"mld")); 
  22.         list.add(instancUser(3,"lq")); 
  23.         list.add(instancUser(4,"gj")); 
  24.         ListObject o = new ListObject(); 
  25.         o.setList(list); 
  26.         return o; 
  27.     } 
  28.      
  29.     private UserDTO instancUser(Integer id,String name){ 
  30.         UserDTO user = new UserDTO(); 
  31.         user.setId(id); 
  32.         user.setName(name); 
  33.         return user; 
  34.     } 
  35. } 

/**
* WebService实现类.
*
* 使用@WebService指向Interface定义类即可.
*/
@WebService(endpointInterface = "cn.org.coral.biz.examples.webservice.WebServiceSample")
public class WebServiceSampleImpl implements WebServiceSample {

public String sayUserName(UserDTO user) {
return "hello "+user.getName();
}

public String say(String hello) {
return "hello "+hello;
}

public ListObject findUsers() {
ArrayList<Object> list = new ArrayList<Object>();

list.add(instancUser(1,"lib"));
list.add(instancUser(2,"mld"));
list.add(instancUser(3,"lq"));
list.add(instancUser(4,"gj"));
ListObject o = new ListObject();
o.setList(list);
return o;
}

private UserDTO instancUser(Integer id,String name){
UserDTO user = new UserDTO();
user.setId(id);
user.setName(name);
return user;
}
}



4.依赖的两个类:用户对象与List对象
Java代码

   1. /**
   2.  * Web Service传输User信息的DTO.
   3.  * 
   4.  * 分离entity类与web service接口间的耦合,隔绝entity类的修改对接口的影响.
   5.  * 使用JAXB 2.0的annotation标注JAVA-XML映射,尽量使用默认约定.
   6.  * 
   7.  */ 
   8. @XmlAccessorType(XmlAccessType.FIELD) 
   9. @XmlType(name = "User") 
  10. public class UserDTO { 
  11.  
  12.     protected Integer id; 
  13.  
  14.     protected String name; 
  15.  
  16.     public Integer getId() { 
  17.         return id; 
  18.     } 
  19.  
  20.     public void setId(Integer value) { 
  21.         id = value; 
  22.     } 
  23.  
  24.     public String getName() { 
  25.         return name; 
  26.     } 
  27.  
  28.     public void setName(String value) { 
  29.         name = value; 
  30.     } 
  31. } 

/**
* Web Service传输User信息的DTO.
*
* 分离entity类与web service接口间的耦合,隔绝entity类的修改对接口的影响.
* 使用JAXB 2.0的annotation标注JAVA-XML映射,尽量使用默认约定.
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "User")
public class UserDTO {

protected Integer id;

protected String name;

public Integer getId() {
return id;
}

public void setId(Integer value) {
id = value;
}

public String getName() {
return name;
}

public void setName(String value) {
name = value;
}
}


关于List对象,参照了有关JWS的一个问题中的描述:DK6.0 自带的WebService中 WebMethod的参数好像不能是ArrayList 或者其他List
传递List需要将List 包装在其他对象内部才行 (个人理解 如有不对请指出) ,我在实践中也遇到了此类问题.通过以下封装的对象即可以传递List对象.
Java代码

   1. /**
   2.  * <p>Java class for listObject complex type.
   3.  * 
   4.  * <p>The following schema fragment specifies the expected content contained within this class.
   5.  * 
   6.  * <pre>
   7.  * <complexType name="listObject">
   8.  *   <complexContent>
   9.  *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
  10.  *       <sequence>
  11.  *         <element name="list" type="{http://www.w3.org/2001/XMLSchema}anyType" maxOccurs="unbounded" minOccurs="0"/>
  12.  *       </sequence>
  13.  *     </restriction>
  14.  *   </complexContent>
  15.  * </complexType>
  16.  * </pre>
  17.  * 
  18.  * 
  19.  */ 
  20. @XmlAccessorType(XmlAccessType.FIELD) 
  21. @XmlType(name = "listObject", propOrder = { "list" }) 
  22. public class ListObject { 
  23.  
  24.     @XmlElement(nillable = true) 
  25.     protected List<Object> list; 
  26.  
  27.     /**
  28.      * Gets the value of the list property.
  29.      * 
  30.      * <p>
  31.      * This accessor method returns a reference to the live list,
  32.      * not a snapshot. Therefore any modification you make to the
  33.      * returned list will be present inside the JAXB object.
  34.      * This is why there is not a <CODE>set</CODE> method for the list property.
  35.      * 
  36.      * <p>
  37.      * For example, to add a new item, do as follows:
  38.      * <pre>
  39.      *    getList().add(newItem);
  40.      * </pre>
  41.      * 
  42.      * 
  43.      * <p>
  44.      * Objects of the following type(s) are allowed in the list
  45.      * {@link Object }
  46.      * 
  47.      * 
  48.      */ 
  49.     public List<Object> getList() { 
  50.         if (list == null) { 
  51.             list = new ArrayList<Object>(); 
  52.         } 
  53.         return this.list; 
  54.     } 
  55.  
  56.     public void setList(ArrayList<Object> list) { 
  57.         this.list = list; 
  58.     } 
  59.  
  60. } 

/**
* <p>Java class for listObject complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="listObject">
*   <complexContent>
*     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
*       <sequence>
*         <element name="list" type="{http://www.w3.org/2001/XMLSchema}anyType" maxOccurs="unbounded" minOccurs="0"/>
*       </sequence>
*     </restriction>
*   </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "listObject", propOrder = { "list" })
public class ListObject {

@XmlElement(nillable = true)
protected List<Object> list;

/**
* Gets the value of the list property.
*
* <p>
* This accessor method returns a reference to the live list,
* not a snapshot. Therefore any modification you make to the
* returned list will be present inside the JAXB object.
* This is why there is not a <CODE>set</CODE> method for the list property.
*
* <p>
* For example, to add a new item, do as follows:
* <pre>
*    getList().add(newItem);
* </pre>
*
*
* <p>
* Objects of the following type(s) are allowed in the list
* {@link Object }
*
*
*/
public List<Object> getList() {
if (list == null) {
list = new ArrayList<Object>();
}
return this.list;
}

public void setList(ArrayList<Object> list) {
this.list = list;
}

}



5.WebService 服务端 spring 配置文件 ws-context.xml
Xml代码

   1. <beans xmlns="http://www.springframework.org/schema/beans" 
   2.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   3.     xmlns:jaxws="http://cxf.apache.org/jaxws" 
   4.     xsi:schemaLocation="http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd" 
   5.     default-autowire="byName" default-lazy-init="true"> 
   6.      
   7.     <jaxws:endpoint id="webServiceSample" 
   8.         address="/WebServiceSample" implementor="cn.org.coral.biz.examples.webservice.WebServiceSampleImpl"/> 
   9.  
  10. </beans> 

<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://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName" default-lazy-init="true">

<jaxws:endpoint id="webServiceSample"
address="/WebServiceSample" implementor="cn.org.coral.biz.examples.webservice.WebServiceSampleImpl"/>

</beans>



WebService 客户端 spring 配置文件 wsclient-context.xml
Xml代码

   1. <beans xmlns="http://www.springframework.org/schema/beans" 
   2.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   3.     xmlns:jaxws="http://cxf.apache.org/jaxws" 
   4.     xsi:schemaLocation="http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd" 
   5.     default-autowire="byName" default-lazy-init="true"> 
   6.  
   7.     <!-- ws client --> 
   8.     <bean id="identityValidateServiceClient" class="cn.org.coral.admin.service.IdentityValidateService" 
   9.         factory-bean="identityValidateServiceClientFactory" factory-method="create" /> 
  10.  
  11.     <bean id="identityValidateServiceClientFactory" 
  12.         class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean"> 
  13.         <property name="serviceClass" 
  14.             value="cn.org.coral.admin.service.IdentityValidateService" /> 
  15.         <property name="address" 
  16.             value="http://88.148.29.54:8080/coral/services/IdentityValidateService"/> 
  17.     </bean> 
  18.      
  19. </beans> 

<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://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="byName" default-lazy-init="true">

<!-- ws client -->
<bean id="identityValidateServiceClient" class="cn.org.coral.admin.service.IdentityValidateService"
factory-bean="identityValidateServiceClientFactory" factory-method="create" />

<bean id="identityValidateServiceClientFactory"
class="org.apache.cxf.jaxws.JaxWsProxyFactoryBean">
<property name="serviceClass"
value="cn.org.coral.admin.service.IdentityValidateService" />
<property name="address"
value="http://88.148.29.54:8080/coral/services/IdentityValidateService"/>
</bean>

</beans>


6.发布到tomcat服务器以后通过以下地址即可查看自定义的webservice接口生成的wsdl:
http://88.148.29.54:8080/aio/services/WebServiceSample?wsdl

7.调用WebService接口的Junit单元测试程序
Java代码

   1. package test.coral.sample; 
   2.  
   3. import org.springframework.test.AbstractDependencyInjectionSpringContextTests; 
   4.  
   5. import cn.org.coral.biz.examples.webservice.WebServiceSample; 
   6. import cn.org.coral.biz.examples.webservice.dto.UserDTO; 
   7.  
   8. public class TestWebServiceSample extends 
   9.         AbstractDependencyInjectionSpringContextTests { 
  10.     WebServiceSample webServiceSampleClient; 
  11.  
  12.     public void setWebServiceSampleClient(WebServiceSample webServiceSampleClient) { 
  13.         this.webServiceSampleClient = webServiceSampleClient; 
  14.     } 
  15.      
  16.     @Override 
  17.     protected String[] getConfigLocations() { 
  18.         setAutowireMode(AUTOWIRE_BY_NAME); 
  19.                   //spring 客户端配置文件保存位置 
  20.         return new String[] { "classpath:/cn/org/coral/biz/examples/webservice/wsclient-context.xml" }; 
  21.     } 
  22.      
  23.     public void testWSClinet(){ 
  24.         Assert.hasText(webServiceSampleClient.say(" world")); 
  25.     } 
  26. } 

你可能感兴趣的:(apache,spring,Web,xml,webservice)