OpenJWeb中使用cxf webservice搭建跨平台SOA框架

    在企业应用开发中,为了实现应用之间的松耦合,避免应用之间的过度依赖,可以使用WebService和socket通信这两种跨平台的解决方案。因为openjweb框架中整合了apache cxf框架,所以openjweb快速开发平台本身也是一个WebService服务器。在openjweb平台中为各子系统设计cxf webservice服务器端接口服务,可以实现其他异构应用系统请求openjweb各子系统提供的服务。比如其他应用系统从openjweb中获取openjweb系统里的部门信息。

    在openjweb中用cxf开发webservice非常简单,一般可针对每个子系统设计一个webservice 服务器端组件,具体接口功能可视具体应用而定。下面介绍在openjweb中开发cxf服务端接口的过程:

    (1)首先在D:\project\openjweb\src\java\applicationContext-cxf.xml中,定义一个webservice服务器端组件(当前示例为门店子系统定义一个服务器端组件):

           <!--门店服务端-->
 
 <jaxws:endpoint id="IStoreWS" implementor="com.tzsoft.store.ws.StoreWSImpl" address="/storeWS">
      <jaxws:inInterceptors>
     <bean  class="org.openjweb.core.webservice.cxf.service.ServerAuthIntercepter"></bean>
        </jaxws:inInterceptors>
 </jaxws:endpoint>

        这里要实现一个门店应用的WebService服务器端接口类IStoreWS.java和实现类StoreWSImpl.java,注意IStoreWS.java和应用系统自己的业务逻辑接口不同,IStoreWS.java

声明的只是为了给外部调用的WebService接口,在职责上和子系统内部声明的业务逻辑接口是有不同用途的。前者是粗粒度的,后者是细粒度的。下面是IStoreWS.java代码:

package com.tzsoft.store.ws;

import javax.jws.WebParam;
import javax.jws.WebService;

/**
 * WebService接口定义类.
 *
 * 使用@WebService将接口中的所有方法输出为Web Service.
 * 可用annotation对设置方法、参数和返回值在WSDL中的定义.
 */
@WebService
public interface IStoreWS
{
 /**
  * 上传会员卡号
  * @param comId 单位编码
  * @param deptId 部门编码
  * @param memCard
  * @return
  */
 
 String uploadMemCard(
   @WebParam(name = "comId")String comId,
   @WebParam(name = "deptId")String deptId,
   @WebParam(name = "memCard")String memCard) ;
}

 

 

下面是实现类:

package com.tzsoft.store.ws;

import javax.annotation.Resource;
import javax.jws.WebService;

import com.tzsoft.store.service.IStoreService;

//import org.openjweb.core.service.IUserAuthService;
@WebService(endpointInterface = "com.tzsoft.store.ws.IStoreWS")
public class StoreWSImpl implements IStoreWS
{
 @Resource(name = "IStoreService")
 IStoreService storeService;
 
 public String uploadMemCard(String comId, String deptId, String memCard) 
 {
  String s = "success";
  try
  {
   System.out.println("下面会员卡调用.....");
   
   storeService.receiveMemCard(comId, deptId, memCard);
  }
  catch(Exception ex)
  {
   
  }
  return "哈哈 ,成功了耶!";
 }
 
}
注意代码里的@WebService注解的使用。

因为WebService是跨平台的调用,所以可以向指定的WebService地址发送SOAP包就可以了。下面介绍如何向门店WebService地址发送调用请求并返回调用结果。

操作过程:

(1)建立一个批处理文件,内容:

        java -classpath . SOAPClient4XG http://localhost:8088/portal/services/storeWS cxf4.xml

(2)创建一个SOAPClient4XG.java类并编译,此类用于将基于SOAP格式的xml请求文件发送到WebService地址执行WebService调用,并返回执行结果:

     

import java.io.*;
import java.net.*;

public class SOAPClient4XG {
    public static void main(String[] args) throws Exception {

        if (args.length  < 2) {
            System.err.println("Usage:  java SOAPClient4XG " +
                               "http://soapURL soapEnvelopefile.xml" +
                               " [SOAPAction]");
    System.err.println("SOAPAction is optional.");
            System.exit(1);
        }

        String SOAPUrl      = args[0];
        String xmlFile2Send = args[1];

    String SOAPAction = "";
        if (args.length  > 2)
    SOAPAction = args[2];
    
        // Create the connection where we're going to send the file.
        URL url = new URL(SOAPUrl);
        URLConnection connection = url.openConnection();
        HttpURLConnection httpConn = (HttpURLConnection) connection;

        // Open the input file. After we copy it to a byte array, we can see
        // how big it is so that we can set the HTTP Cotent-Length
        // property. (See complete e-mail below for more on this.)

        FileInputStream fin = new FileInputStream(xmlFile2Send);

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
   
        // Copy the SOAP file to the open connection.
        copy(fin,bout);
        fin.close();

        byte[] b = bout.toByteArray();

        // Set the appropriate HTTP parameters.
        httpConn.setRequestProperty( "Content-Length",
                                     String.valueOf( b.length ) );
        httpConn.setRequestProperty("Content-Type","text/xml; charset=utf-8");
    httpConn.setRequestProperty("SOAPAction",SOAPAction);
        httpConn.setRequestMethod( "POST" );
        httpConn.setDoOutput(true);
        httpConn.setDoInput(true);

        // Everything's set up; send the XML that was read in to b.
        OutputStream out = httpConn.getOutputStream();
        out.write( b );   
        out.close();

        // Read the response and write it to standard out.

        InputStreamReader isr =
            new InputStreamReader(httpConn.getInputStream());
        BufferedReader in = new BufferedReader(isr);

        String inputLine;

        while ((inputLine = in.readLine()) != null)
            System.out.println(inputLine);

        in.close();
    }

  // copy method from From E.R. Harold's book "Java I/O"
  public static void copy(InputStream in, OutputStream out)
   throws IOException {

    // do not allow other threads to read from the
    // input or write to the output while copying is
    // taking place

    synchronized (in) {
      synchronized (out) {

        byte[] buffer = new byte[256];
        while (true) {
          int bytesRead = in.read(buffer);
          if (bytesRead == -1) break;
          out.write(buffer, 0, bytesRead);
        }
      }
    }
  }
}

(3)创建一个xml请求调用文件,格式是cxf的客户端xml书写格式:

       

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soap:Header>
  <auth:authentication xmlns:auth="http://localhost:8088/portal//authentication">
  <auth:systemID>1</auth:systemID>
  <auth:userID>test</auth:userID>
  <auth:password>test</auth:password>
 </auth:authentication>

 </soap:Header>
    <soap:Body>
        <ns1:uploadMemCard xmlns:ns1="http://ws.store.tzsoft.com/">
            <comId>C0001</comId>
            <deptId>C0001</deptId>
            <memCard>0001</memCard>
        </ns1:uploadMemCard>
    </soap:Body>
</soap:Envelope>

上面的uploadMemCard是调用门店webService的上传会员卡号的方法,注意xmlns:ns1=http://ws.store.tzsft.com/"这个对应的IStoreWS的目录路径,不过是反着写的。

(4)执行批处理文件会返回调用结果:

<soap:Envelope xmlns:soap=" http://schemas.xmlsoap.org/soap/envelope/">

<soap:Body>

<ns2:uploadMemCardResponse xmlns:ns2=" http://ws.store.tzsoft.com/"><return >哈哈
 ,成功了耶!</return>

</ns2:uploadMemCardResponse>

</soap:Body>

</soap:Envelope>

 

这种调用方式是发送xml流的方式,特点是不受编程语言的限制。但是需要知道发送 的SOAP包的具体格式。另外对响应包也要进行xml解析才能取得具体结果。

 

如果使用Java客户端调用,可参考下面的例子(这个例子带了一个加密头,即SOAP Header中嵌入用户名和密码):

public class TestCxfClient

{

public static String testStoreWS(String wsAddr,String comId,String deptId,String memCard,boolean isSecret)
 {
  JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
  AddSoapHeader ash = new AddSoapHeader();
  if(isSecret)
  {
   logger.info("带加密头a............!");
   ArrayList list = new ArrayList();
      // 添加soap header 信息
      list.add(ash);
      //注入拦截器,getOutInterceptors代表调用服务端时触发,getInInterceptors就是被调用才触发
       factory.setOutInterceptors(list);
  }
  else
  {
   System.out.println("不带加密头,如果不带加密头,需去掉applicationContext-cxf.xml中配置的拦截器............");
  }
  
  factory.setServiceClass(IStoreWS.class);//实例化ws
  factory.setAddress(wsAddr);
  Object obj = factory.create();
  IStoreWS service = (IStoreWS)obj; 
  //下面这行代码是具体调用服务段的deleteTeskTask()
  String msg = "";
     try
     {
      msg = service.uploadMemCard(comId, deptId,memCard);
     }
     catch(Exception ex)
     {
      ex.printStackTrace();
      logger.error(ex.toString());
     }
  return msg;
 }

}

为了在客户端调用时增加SOAP Header以便在 SOAP Header中写入用户名和口令,需要在applicationContext-cxf.xml配置文件中加入拦截器:

    <jaxws:client id="clientTestService" serviceClass="org.openjweb.core.webservice.cxf.service.TestCxfClient"
        address="http://localhost:8088/portal/services/cxfDemoWS">
        <jaxws:outInterceptors>
      <bean class="org.apache.cxf.binding.soap.saaj.SAAJInInterceptor" />  
            <ref bean="wsOutInterceptor"/>
        </jaxws:outInterceptors>
    </jaxws:client>

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值