一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

Apache CXF实现一个纯的JAX-WS web service

时间:2015-12-02 编辑:简简单单 来源:一聚教程网

先在Eclipse中新建一个Java Project

(可以不是WTP的Dynamic Web Project)
 

选择Java Project


再看pom.xml

我们使用cxf 3.1.4版本,

    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    4.0.0
    com.cnblog.richaaaard.cxfstudy
    cxf-test-standalone-ws-helloworld
    war
    1.0-SNAPSHOT
    cxf-test-standalone-ws-helloworld Maven Webapp
    http://maven.apache.org
       
   



        3.1.4       
   

       
   
       
            org.apache.cxf
            cxf-rt-frontend-jaxws
            ${cxf.version}
       

       
            org.apache.cxf
            cxf-rt-transports-http
            ${cxf.version}
       

       
            org.apache.cxf
            cxf-rt-transports-http-jetty
            ${cxf.version}
       

       
            org.apache.cxf
            cxf-rt-ws-security
            ${cxf.version}
       

       
            org.apache.cxf
            cxf-rt-ws-policy
            ${cxf.version}
       






       
            javax.ws.rs
            jsr311-api
            1.1.1
       

       
            org.slf4j
            slf4j-api
            1.5.8
       

      
            org.slf4j
            slf4j-simple
            1.5.8
       

       
            commons-httpclient
            commons-httpclient
            3.0
       

       
            commons-io
            commons-io
            2.3
       

       
            junit
            junit
            4.8.1
            test
       

   

       
   
        cxfstudy
       
           
                src/main/resources
           

           
                src/main/java
                <includes>
                    **
               
               
                    **/*.java
               

           

       

       
           
                org.mortbay.jetty
                maven-jetty-plugin
               
                    /
                   
                       
                            9000
                       

                   

               

           

           
                org.apache.maven.plugins
                maven-compiler-plugin
               
                    1.7
                    1.7
               

           

       

   

   


另外有例子给出的slf4j是slf4j-jdk14 (http://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14)的版本,如果用jdk5以上的同学可以将其替换成slf4j-simple实现。


CXF Web Service (Annotation)实现,上代码

CXF支持两种方式发布一个web service,一种是Java Annotation(Bottom up),另外一种是先定义好wsdl和xsd schema然后通过工具生成(Top down),我们这里的例子先介绍Java Annotation。

首先我们需要定义一个web service接口类HelloWorld,并加上Annotation

package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services;
 
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
 
@WebService
public interface HelloWorld {
    @WebMethod
    @WebResult String sayHi(@WebParam String text);
}

在此我们先不介绍 @WebService、 @WebMethod、@WebResult还有@WebParam如何工作的。

然后我们需要用HelloWorldImpl来实现这个接口类,

package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services;
 
public class HelloWorldImpl implements HelloWorld {
    public String sayHi(String name) {
        String msg = "Hello " + name + "!";
        return msg;
    }
}


发布一个Web Service

我们先用一个最简单的方式,使用javax.xml.ws.Endpoint来发布

package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.server;
 
import javax.xml.ws.Endpoint;
 
import com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorldImpl;
 
public class SimpleServer {
     
    public static void main(String[] args) throws Exception {
         
        System.out.println("Starting Server");
        HelloWorldImpl implementor = new HelloWorldImpl();
        String address = "http://localhost:9000/ws/HelloWorld";
        Endpoint.publish(address, implementor);
    }
}

注意:这里的address路径是大小写敏感的,如果发布成"http://localhost:9000/ws/helloWorld",而客户端使用/HelloWorld会找不到服务。

直接Run As..-> Java Application


我们可以在Eclipse中看到一个jetty服务正常运行
Starting Server
128 [main] INFO org.apache.cxf.service.factory.ReflectionServiceFactoryBean - Creating Service {http://services.helloworld.ws.standalone.cxftest.richaaaard.cnblog.com/}HelloWorldImplService from class com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorld
487 [main] INFO org.apache.cxf.endpoint.ServerImpl - Setting the server's publish address to be http://localhost:9000/ws/HelloWorld
506 [main] INFO org.eclipse.jetty.server.Server - jetty-8.1.15.v20140411
554 [main] INFO org.eclipse.jetty.server.AbstractConnector - Started SelectChannelConnector@localhost:9000

此时,我们通过浏览器访问http://localhost:9000/ws/HelloWorld?WSDL



如何访问我们发布的这个服务呢?

我们利用jaxws中的JaxWsProxyFactoryBean来消费这个服务

package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.client;
 
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
 
import com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorld;
 
public class Client {
    public static void main(String[] args) {
        JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
       factory.getInInterceptors().add(new LoggingInInterceptor());
        factory.getOutInterceptors().add(new LoggingOutInterceptor());

        factory.setServiceClass(HelloWorld.class);
        factory.setAddress("http://localhost:9000/ws/HelloWorld");
        HelloWorld helloworld = (HelloWorld) factory.create();
        String reply = helloworld.sayHi("HI");
        System.out.println("Server said: " + reply);
        System.exit(0);
    }
}

同样右键选择Client.java,Run As.. ->Java Application,我们可以看到运行后台执行的日志最后成功返回“Server said: Hello HI!”

114 [main] INFO org.apache.cxf.service.factory.ReflectionServiceFactoryBean - Creating Service {http://services.helloworld.ws.standalone.cxftest.richaaaard.cnblog.com/}HelloWorldService from class com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorld
531 [main] INFO org.apache.cxf.services.HelloWorldService.HelloWorldPort.HelloWorld - Outbound Message
---------------------------
ID: 1
Address: http://localhost:9000/ws/HelloWorld
Encoding: UTF-8
Http-Method: POST
Content-Type: text/xml
Headers: {Accept=[*/*], SOAPAction=[""]}
Payload: HI
--------------------------------------
748 [main] INFO org.apache.cxf.services.HelloWorldService.HelloWorldPort.HelloWorld - Inbound Message
----------------------------
ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {Content-Length=[258], content-type=[text/xml;charset=UTF-8], Server=[Jetty(8.1.15.v20140411)]}
Payload: Hello HI!
--------------------------------------
Server said: Hello HI!

上面Outbound Message和Inbound Message是我们加的两个Logging Interceptor输出的日志,关于Interceptor的原理和更多使用方式,会专题介绍。


这样就完成了一个Web Service的发布和消费

 
*服务端的扩展

除了用一个最简单的javax.xml.ws.Endpoint来发布CXF web service,我们还可以使用cxf-rt-frontend-jaxws.jar中的JaxWsServerFactoryBean来发布一个web service,它可以让我们更多的控制web service的行为,比如说加Logging Interceptor之类

package com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.server;
 
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
 
import com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorld;
import com.cnblog.richaaaard.cxftest.standalone.ws.helloworld.services.HelloWorldImpl;
 
public class Server {
     
    public static void main(String[] args) throws Exception {
        JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
        factory.setServiceClass(HelloWorld.class);
        HelloWorldImpl implementor = new HelloWorldImpl();
        factory.setServiceBean(implementor);
       factory.getInInterceptors().add(new LoggingInInterceptor());
        factory.getOutInterceptors().add(new LoggingOutInterceptor());

        factory.setAddress("http://localhost:9000/ws/HelloWorld");
        factory.create();
   
        System.out.println("Server start...");
        Thread.sleep(60 * 1000);
        System.out.println("Server exit...");
        System.exit(0);
    }
}

  

 
Web Service的CXF实现(Spring整合方式)

新建Java Web项目,采用maven管理jar包,本文章只是提供核心代码文件如下:

(1)maven的pom.xml

(2)cxf-base.xml

(3)cxf-bz-client.xml 客户端配置

(4)cxf-bz-server.xml服务端配置

(5)WSOrderService 业务接口定义

(6)WSOrderServiceImpl 业务接口实现

(7)BZClientHandler,BZServiceHandler 用户认证拦截

(8)web.xml 项目web配置

(9)demo.properties url和用户配置信息

备注:其中涉及spring相关配置文件未列出。

 

1) 主要核心pom.xml配置如下:

  
 
   org.springframework
   spring-aop
   ${spring.version}
 

 
   org.springframework
   spring-asm
   ${spring.version}
 

 
   org.springframework
   spring-beans
   ${spring.version}
 

 
   org.springframework
   spring-context
   ${spring.version}
 

 
   org.springframework
   spring-core
   ${spring.version}
 

 
   org.springframework
   spring-expression
   ${spring.version}
 

 
   org.springframework
   spring-jdbc
   ${spring.version}
 

 
   org.springframework
   spring-orm
   ${spring.version}
 

 
   org.springframework
   spring-tx
   ${spring.version}
 

 
   org.springframework
   spring-web
   ${spring.version}
 

 
   org.springframework
   spring-context-support
   ${spring.version}
 

 
   
 
 
   org.apache.cxf
   cxf-rt-frontend-jaxws
   ${cxf.version}
 

 
    org.apache.cxf
    cxf-rt-transports-common
    2.5.4
    jar
    compile
 

 
    org.apache.cxf
    cxf-rt-core
    ${cxf.version}
    jar
    compile
 

 
    org.apache.cxf
    cxf-rt-transports-http-jetty
    ${cxf.version}
    jar
    compile
 

 

(2)cxf-base.xml


    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xmlns:http-conf="http://cxf.apache.org/transports/http/configuration"
    xsi:schemaLocation="   
        http://www.springframework.org/schema/beans    
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd   
        http://cxf.apache.org/jaxws    
        http://cxf.apache.org/schemas/jaxws.xsd
        http://cxf.apache.org/transports/http/configuration
        http://cxf.apache.org/schemas/configuration/http-conf.xsd">  
         
 
 
 

   
   
     
   
   
   
   


(3)cxf-bz-client.xml


 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"
 default-lazy-init="true">
 
 
     
    
   

   

 
 
  
 

   
 



(4)cxf-bz-server.xml


 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xmlns:tx="http://www.springframework.org/schema/tx"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:jaxws="http://cxf.apache.org/jaxws"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd"
 default-lazy-init="true">

 
    
    
   

   
    
     
    

    
    
     
    

   
 


 

(5)WSOrderService定义业务接口

package com.lshop.ws.server.bz.order.service;
import java.util.Date;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;
import com.lshop.ws.server.bz.order.bean.LvOrderDtoResposne;
 
@WebService(name = "WSOrderService")
@SOAPBinding(style=Style.RPC)
public interface WSOrderService  {
 /**
  * 同步已经审核的订单到商务接口定义
  * @Method: synAuditOrderToBZ
  * @Description:  
  * @param startTime  审核开始时间
  * @param endTime    审核结算时间
  * @return OrderList
  */
 public LvOrderDtoResposne synAuditOrderToBZ(
   @WebParam(name = "startTime") String startTime,
   @WebParam(name = "endTime") String endTime);
 
}

(6)WSOrderServiceImpl业务实现类

package com.lshop.ws.server.bz.order.service;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.jws.WebService;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import com.gv.core.hibernate3.HibernateBaseDAO;
import com.gv.core.service.impl.BaseServiceImpl;
import com.gv.core.util.ObjectUtils;
import com.lshop.common.pojo.logic.LvOrderDetails;
import com.lshop.common.pojo.logic.LvOrderPackageDetails;
import com.lshop.common.util.DateUtils;
import com.lshop.ws.server.bz.order.bean.LvOrderDto;
import com.lshop.ws.server.bz.order.bean.LvOrderDtoResposne;
import com.lshop.ws.server.bz.order.bean.LvProductDto;
import com.lshop.ws.server.bz.order.bean.Result;
 
@Service("WSOrderService")
@WebService(endpointInterface = "com.lshop.ws.server.bz.order.service.WSOrderService")
public class WSOrderServiceImpl extends BaseServiceImpl implements WSOrderService {
 @Resource
 private HibernateBaseDAO dao;
 
 private static final Log logger = LogFactory.getLog(WSOrderServiceImpl.class);
 
 /**
  * 同步已经审核的订单到商务接口定义
  * @Method: synAuditOrderToBZ
  * @Description:  
  * @param startTime  审核开始时间(查询范围起始时间,格式:yyyy-mm-dd HH:mm:ss)
  * @param endTime    审核结束时间(查询范围结束时间,格式:yyyy-mm-dd HH:mm:ss)
  * @return OrderList
  */
 @Override
 public LvOrderDtoResposne synAuditOrderToBZ(String startTime, String endTime) {
  if(logger.isInfoEnabled()){
     logger.info("*****WSOrderServiceImpl.synAuditOrderToBZ() method begin*****");
  }
   
  LvOrderDtoResposne lvOrderDtoResposne=new LvOrderDtoResposne();
  List orderList=new ArrayList();
  //判断查询日期时间差
   
  //根据审核时间查询已经审核订单集合
  try {
   if(ObjectUtils.isNotEmpty(startTime)&&ObjectUtils.isNotEmpty(endTime)){
    String hql=" select DISTINCT ls.ord as ord from  LvOrderLogs ls,LvOrder o " +
      " where ls.ord=o.oid " +
      " and o.isServiceAudit=1 " +
      " and o.isFinanceAudit=1 " +
      " and o.isdelete=0 " +
      " and ls.createTime>=:startTime and ls.createTime <=:endTime ";
    Map param=new HashMap();
    param.put("startTime", DateUtils.convertToDateTime(startTime));
    param.put("endTime", DateUtils.convertToDateTime(endTime));
    List listTmp = dao.getMapListByHql(hql, param).getList();
    if(ObjectUtils.isNotEmpty(listTmp)){
     for (int i = 0; i < listTmp.size(); i++) {
      Map map=(Map) listTmp.get(i);
      //查询订单信息
      LvOrderDto lvOrderDto=this.getOrderInfo(String.valueOf(map.get("ord")));
         orderList.add(lvOrderDto);
     }
    }
   }
   lvOrderDtoResposne.setOrderList(orderList);
   lvOrderDtoResposne.getResult().setStatus(Result.STATUS_SUCCEED);
   lvOrderDtoResposne.getResult().setMessage("成功");
  } catch (Exception e) {
   lvOrderDtoResposne.getResult().setStatus(Result.STATUS_FAIL);
   lvOrderDtoResposne.getResult().setMessage(e.getMessage());
   e.printStackTrace();
  }
   
  if(logger.isInfoEnabled()){
   logger.info("*****WSOrderServiceImpl.synAuditOrderToBZ() method end*****");
  }
  return lvOrderDtoResposne;
 }
 
 
 /**
  *
  * @Method: getOrderDetailsByOid
  * @Description: 根据订单号查询订单详情及对应的产品信息
  * @param oid  订单号
  * @return List
  */
 protected List getOrderDetailsByOid(String oid){
   
  return null;
 }
 
 /**
  *
  * @Method: getOrderInfo
  * @Description: 根据订单号查询订单
  * @param oid  订单号
  * @return List
  */
 protected LvOrderDto getOrderInfo(String oid){
   
  return null;
 }
}

(7)BZClientHandler,BZServiceHandler用户认证拦截。

package com.lshop.ws.util;
import java.io.IOException;
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.ws.soap.SOAPFaultException;
 
public class BZClientHandler implements SOAPHandler {
 
 private String accountNum;
 private String password;
 
  public String getAccountNum() {
  return accountNum;
 }
 public void setAccountNum(String accountNum) {
  this.accountNum = accountNum;
 }
 public String getPassword() {
  return password;
 }
 public void setPassword(String password) {
  this.password = password;
 }
 @Override
    public boolean handleMessage(SOAPMessageContext context) {
   
  System.out.println("Server : handleMessage()......");
   
   
  try{
      SOAPMessage soapMsg = context.getMessage();
      SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
         SOAPHeader soapHeader = soapEnv.getHeader();
   
             //if no header, add one
      if (soapHeader == null){
              soapHeader = soapEnv.addHeader();
       }
   
        
      SOAPElement accountNumNode = soapHeader.addChildElement(new QName("http://service.webservice.datainterface.bz.gv.com/","accountNum"));
      accountNumNode.setNodeValue("accountNum");
      accountNumNode.setValue(accountNum);
       
      SOAPElement passwordNode = soapHeader.addChildElement(new QName("http://service.webservice.datainterface.bz.gv.com/","password"));
      passwordNode.setNodeValue("password");
      passwordNode.setValue(password);
    
      soapMsg.writeTo(System.out);
      return true;
   
   }catch(SOAPException e){
    System.err.println(e);
   }catch(IOException e){
    System.err.println(e);
   }
   
   
    //continue other handler chain
    return false;
  }
   
  @Override
  public boolean handleFault(SOAPMessageContext context) {
   
   System.out.println("Server : handleFault()......");
   
   return true;
  }
   
  @Override
  public void close(MessageContext context) {
   System.out.println("Server : close()......");
  }
   
  @Override
  public Set getHeaders() {
   System.out.println("Server : getHeaders()......");
   return null;
  }
   
      private void generateSOAPErrMessage(SOAPMessage msg, String reason) {
        try {
           SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
           SOAPFault soapFault = soapBody.addFault();
           soapFault.setFaultString(reason);
           throw new SOAPFaultException(soapFault);
        }
        catch(SOAPException e) { }
     }
}

(8)web.xml配置web servcie请求拦截url.

 
 
   
        cxf  
        org.apache.cxf.transport.servlet.CXFServlet  
        1  
   
 
     
        cxf  
        /ws/*  
   
 
 

(9)demo.properties

bz.sys.url=http\://127.0.0.1\:8080
bz.ws.account=demo
bz.ws.password=demo400

 

配置完成可以通过下面的服务端url访问:

http://127.0.0.1:8080/ws/WSOrderService?wsdl

客户端先生成客户端java文件,在调用接口实现即可。

热门栏目