WebService开发笔记(一)-- 利用cxf开发WebService竟然如此简单

现在的项目中需要用到SOA概念的地方越来越多,最近我接手的一个项目中就提出了这样的业务要求,需要在.net开发的客户端系统中访问java开发的web系统,这样的业务需求自然需要通过WebService进行信息数据的操作。下面就将我们在开发中摸索的一点经验教训总结以下,以供大家参考. 
我们项目的整个架构使用的比较流行的WSH MVC组合,即webwork2 + Spring + Hibernate; 
1.首先集成Apacha CXF WebService 到 Spring 框架中; 
apache cxf 下载地址>>: 
(1)在spring context配置文件中引入以下cxf配置 
***************************************************************************** 
<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" />   
<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" /> 
***************************************************************************** 
(2)在web.xml中添加过滤器: 
***************************************************************************** 
<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代码 
/**   
* 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(); 
}   
/** 
* 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代码 
/**   
* 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;   
     }   
}   
/** 
* 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代码 
/**   
* 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;   
     }   
}   
/** 
* 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代码 
/**   
* <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;   
     }   
}   
/** 
* <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代码 
<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> 
<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代码 
<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>   
<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代码 
package test.coral.sample; 
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;   
import cn.org.coral.biz.examples.webservice.WebServiceSample;   
import cn.org.coral.biz.examples.webservice.dto.UserDTO;   
public class TestWebServiceSample extends   
         AbstractDependencyInjectionSpringContextTests {   
     WebServiceSample webServiceSampleClient;     
     public void setWebServiceSampleClient(WebServiceSample webServiceSampleClient) {   
         this.webServiceSampleClient = webServiceSampleClient;   
     }   
     @Override   
     protected String[] getConfigLocations() {   
         setAutowireMode(AUTOWIRE_BY_NAME);   
                  //spring 客户端配置文件保存位置   
         return new String[] { "classpath:/cn/org/coral/biz/examples/webservice/wsclient-context.xml" };   
     }   
     public void testWSClinet(){   
         Assert.hasText(webServiceSampleClient.say(" world"));   
     }   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值