我的知识库

知识等于力量

« Jdk1.5中的新特性 --泛型 (详细版)用于实现 Web 服务的 SOA 编程模型,第 4 部分: IBM 企业服务总线介绍 »

j2ee web service开发

之所以把数组类型在调用web service中作为参数的实现郑重的记录下来,实在是因为数组在j2ee web service的实现不是一件容易的问题。至少用Jbossj2ee web service实现时是这样.

 

好象网上关于web service的比较深入一点的资料比较少,关于j2ee web service的资料就更少了. 这里只记录了符合WS I BP 标准的SOAP四种消息传递模式中的RPC/Literal消息传递模式。这个请参考书籍《j2ee web service 高级编程》一书。该书也只能是参考了,只是介绍了web service的理论实现及一点jax-rpc API,并且还有蛮多印刷错字。虽然jax-rpc API的目标之一就是为了在各种java web service实现技术中提供一个便携的手段,然而各种j2ee服务器的web service技术还是有些差别的,这个还是造成了程序不能直接在各种j2ee服务器之间毫无修改的移植。在 apacheaxis实现中,数组作为参数传递根本不值一提,借助工具很方面的就可以实现。

 

但是在jboss中的ws实现中确不是一件便利的事情。因为郁闷了很久,发点牢骚:)具体实现:

 

    作为web service服务实现的类必须实现java.rmi.Remote的接口:

 

package array;

 

 

import java.rmi.Remote;

 

import java.rmi.RemoteException;

 

 

public interface CountUser extends Remote {

 

     public int countUser(User[] user) throws RemoteException;

 

}

 

 

    具体实现远程接口的类:

 

package array;

 

 

public class CountUserImpl implements CountUser {

 

    public int countUser(User[] user){

 

        for(int i=0;i<user.length;i++){

 

            System.out.println("name "+user[i].getName()+"  phone  "+

 

                               user[i].getPhone()+ " birthday "+user[i].getBirthDay());

 

        }

 

        return user.length;

 

    }

 

 

}

 

 

  作为数组参数传递的类:

 

 

package array;

 

 

import java.util.Date;

 

 

public class User {

 

    private String name;

 

    private String phone;

 

    private Date birthDay;

 

 

    public User() {

 

 

    }

 

    public User(String name,String phone,Date birthDay){

 

        this.name=name;

 

        this.phone=phone;

 

        this.birthDay=birthDay;

 

    }

 

 

    public void setName(String name) {

 

        this.name = name;

 

    }

 

 

    public void setPhone(String phone) {

 

        this.phone = phone;

 

    }

 

 

    public void setBirthDay(Date birthDay) {

 

        this.birthDay = birthDay;

 

    }

 

 

    public String getName() {

 

        return name;

 

    }

 

 

    public String getPhone() {

 

        return phone;

 

    }

 

 

    public Date getBirthDay() {

 

        return birthDay;

 

    }

 

 

}

 

 

使用Jboss_Home/bin 下的wstools工具生成布署j2ee web service 必须的三个文件,jax-rpc映射文件,web服务描述器文件,以及wsdl文档用于wstools工具的配置文件jboss-config.xml类容如下:

 

<?xml version="1.0" encoding="UTF-8"?>

 

<configuration xmlns="http://www.jboss.org/jbossws-tools"

 

   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 

   xsi:schemaLocation="http://www.jboss.org/jbossws-tools http://www.jboss.org/jbossws-tools/schema/jbossws-tool_1_0.xsd"

 

  <java-wsdl>

 

  <service  name="ServiceBeanInterface1" style="rpc"   endpoint="array.ServiceBeanInterface1"/>

 

      <namespaces target-namespace="http://array" type-namespace="http://array"/>

 

     <mapping file="ServiceBeanInterface1.xml"/>

 

     <webservices servlet-link="ServiceBeanInterface1"/>     

 

 

 

</java-wsdl>

 

</configuration>

 

使用 wstools -cp array.CountUser -config jboss-config.xml 命令可以生成布署web服务所需的三个文件。另外还得在web.xml文件中把CountUser接口作为servlet发布

 

  <servlet>

 

    <display-name>CountUser Servlet</display-name>

 

    <servlet-name>CountUser</servlet-name>

 

    <servlet-class>array.CountUserImpl</servlet-class>

 

  </servlet>

 

  <servlet-mapping>

 

    <servlet-name>CountUser</servlet-name>

 

    <url-pattern>/CountUser</url-pattern>

 

  </servlet-mapping>

 

  <servlet-mapping>

 

    <servlet-name>CountUser</servlet-name>

 

    <url-pattern>/services/*</url-pattern>

 

  </servlet-mapping>

 

仅仅是这样倒也算很容易了,但是wstools工具并不能在映射文件中正确实现User[]的映射。因此还需要手工添加如下代码以实现User[] xml之间的映射。   

 

    <java-xml-type-mapping>

 

    <java-type>array.User[]</java-type>

 

    <root-type-qname xmlns:typeNS='http://array'>typeNS:User.Array</root-type-ame>

 

    <qname-scope>complexType</qname-scope>

 

    </java-xml-type-mapping>

 

打包成war文件,并且布署。服务端的实现就完成了。打包的war文件下载

 使用的Jboss版本4.04

 j2ee web service 客户端的三种调用方式: (一)占位程序:该种调用方式需要服务端生成所谓的占位程序,也是性能最好的一种方式,据有的文档介绍说用占位程序实现的web服务不能实现各种编程语言比如C#之是互相调用就是会引起互操作性的问题.而且生成占位程序的web服务的确稍麻烦一点,更重要的是我不喜欢这种方式,也就不作备忘了:)。

 

(二)动态代理:该种方式需要一个指向WSDL文档的URL。具体实现:

 

        ServiceFactoryImpl factory = new ServiceFactoryImpl();

 

// 工厂类,取得service对象,

 

 

        URL wsdlURL = new File(  "complexType-array/WEB-INF/wsdl/CountUser.wsdl").                  toURL(); //wsdl 文档的URL 它可以是一个远程的URL 但是本例引用本地硬盘上的一个wsdl文件

 

其好处是提高程序的性能。

 

        URL mappingURL = new File("complexType-array/WEB-INF/CountUser.xml").                         toURL(); // 映射文件的URL 需要着重说明的就是这个映射文件了,标准的j2ee web service API实现中可不需要这玩意,但是在Jboss的实现中不要这个就会报错cannot obtain java mapping type...,在jboss下开发的web 服务客户端移植时需要特别注意,麻烦!

 

        QName qname = new QName("http://array", "CountUserService");

 

        Service service = factory.createService(wsdlURL, qname, mappingURL);// 通过工厂方法得到一个Service对象,但createService(wsdlURL, qname, mappingURL)方法是jboss的具体实现增加一的一个方法,标准API可没有这玩意,对于数组类型的传递只能用这个方法了,奇怪的是客户端居然需要部署在服务器端的映射文件,没劲!       

 

        CountUser port = (CountUser) service.getPort(CountUser.class); // 取得服务器端的接口。

 

( 三)动态调用。

 

 

        URL wsdlURL = new File(

 

                "complexType-array/WEB-INF/wsdl/CountUser.wsdl").

 

                      toURL();

 

        URL mappingURL = new File(

 

                "complexType-array/WEB-INF/CountUser.xml").

 

                         toURL();

 

        QName qname = new QName("http://array", "CountUserService");// 表示服务名QName对象。

 

        Service service = factory.createService(wsdlURL, qname, mappingURL);

 

        Call call = service.createCall();

 

    // 没什么好说的,依然要用到wsdl文档文件,映射文件。

 

        call.setOperationName(new QName(TARGET_NAMESPACE, "countUser"));// 指定方法名

 

        call.setPortTypeName(new QName("CountUser"));// 指定端口名

 

("value",Constants.TYPE_LITERAL_ANYSIMPLETYPE,ParameterMode.IN);

 

        call.setReturnType(Constants.TYPE_LITERAL_INT);

 

        Object retObj = call.invoke(new Object[] {user});

 

 

 

 

服务器端的实现参见j2ee web service()完整的客户端代码如下:

 

package array;

 

 

import java.net.URL;

 

import javax.xml.rpc.*;

 

import javax.xml.namespace.QName;

 

import java.util.*;

 

import java.io.File;

 

import org.jboss.ws.jaxrpc.ServiceFactoryImpl;

 

import org.jboss.ws.Constants;

 

 

public class ArrayExample {

 

     public ArrayExample() {

 

    }

 

 

    private static final String TARGET_NAMESPACE =

 

            "http://array";

 

 

    private CountUser getPort() throws Exception {

 

 

        ServiceFactoryImpl factory = new ServiceFactoryImpl();

 

 

        URL wsdlURL = new File(

 

                "complexType-array/WEB-INF/wsdl/CountUser.wsdl").

 

                      toURL();

 

        URL mappingURL = new File(

 

                "complexType-array/WEB-INF/CountUser.xml").

 

                         toURL();

 

        QName qname = new QName("http://array", "CountUserService");

 

        Service service = factory.createService(wsdlURL, qname, mappingURL);

 

 

        CountUser port = (CountUser) service.getPort(CountUser.class);

 

 

        return port;

 

    }

 

 

    public void testComplexUserArray(User[] user) throws

 

            Exception {

 

        CountUser port = getPort();

 

 

        try {

 

            int returnValue = port.countUser(user);

 

            System.out.print(returnValue);

 

        } catch (Exception e) {

 

            throw e;

 

        }

 

    }

 

 

    public void DIIClient(User[] user) throws Exception {

 

 

        ServiceFactoryImpl factory = new ServiceFactoryImpl();

 

 

        URL wsdlURL = new File(

 

                "complexType-array/WEB-INF/wsdl/CountUser.wsdl").

 

                      toURL();

 

        URL mappingURL = new File(

 

                "complexType-array/WEB-INF/CountUser.xml").

 

                         toURL();

 

        QName qname = new QName("http://array", "CountUserService");

 

        Service service = factory.createService(wsdlURL, qname, mappingURL);

 

        Call call = service.createCall();

 

        call.setOperationName(new QName(TARGET_NAMESPACE, "countUser"));

 

        call.setPortTypeName(new QName("CountUser"));

 

 

        call.setReturnType(Constants.TYPE_LITERAL_INT);

 

 

        Object retObj = call.invoke(new Object[] {user});

 

 

        System.out.println(retObj.toString());

 

    }

 

 

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

 

        ArrayExample arrayexample = new ArrayExample();

 

        User[] user = new User[2];

 

        user[0] = new User(" 张三", "027-88888888", new Date());

 

        user[1] = new User("lisi", null, new Date());

 

        //arrayexample.testComplexUserArray(user);

 

        arrayexample.DIIClient(user);

 

    }

 

}

 

 

 

 至此好象一个可以应用的web service服务就完成了,然而这才仅仅只是开始~~~~~~~~~

Search

导航

热门文章

最新文章

Powered By duduwolf's wiki 1.0

Copyright 1999-2006 duduwolf.com Some Rights Reserved.