欢迎来到:http://observer.blog.51cto.com

webservcie是可以跨语言跨平台开发的一种技术,各种计算机语言都可以搭建服务器,同时各种计算机语言也可以开发客户端。只要有服务器,不管是用java还是C++抑或是php搭建的,其他语言都可以根据其开放的wsdl开发好客户端,然后调用其方法就像调用本地本项目的方法一样。本文使用java开发客户端,例子依赖于上一篇文章:CXF搭建webService服务器;如果有不明白的可以先看此文章再看本文。
第一:下载CXF包
   本文的客户端使用CXF自带工具开发,如果懒得上网找可以到这里下载:apache-cxf-2.6.1.tar

,解压开发包。

第二:配置环境变量
   这一步其实可以忽略,但是如果不配置环境变量,在调用命令是就必须到cxf的bin目录下才能调用,缺乏灵活性,所以本文章对其进行配置。
   liunx下配置:
   调出控制台输入命令:

   ~$ gedit ~/.bashrc
   添加:
       export CXF_HOME=/home/roadahead/apache-cxf-2.6.1
       export CLASSPATH=$CLASSPATH:${CXF_HOME}/lib
       export PATH=$PATH:${CXF_HOME}/bin

自己将“/home/roadahead/apache-cxf-2.6.1”对应到自己的CXF目录。

   保存退出,调用以下命令让其立即生效:
   ~$ source ~/.bashrc

   windows下配置:
   右键“我的电脑”——>“属性”——>“高级”——>“环境变量”
   新建环境变量:
   变量名:CXF_HOME
   变量值:C:\apache-cxf-2.6.1
   变量值是你自己的CXF目录。
   CLASSPATH中添加:;%CXF_HOME%\lib
   PATH中添加:;%CXF_HOME%\bin

自己将“C:\apache-cxf-2.6.1”对应到自己的CXF目录。

   确定完成。

第三:调用命令wsdl2java
   将服务器部署好(这里如果不会服务器的部署,自己面壁去),调出控制台,调用如下命令:

~$ wsdl2java -d /home/roadahead/workspace/webServiceClient/src  http://127.0.0.1:8080/webServiceCXF/services/Service?wsdl
   这里-d后面跟的是生成的客户端代码所放的位置,这里放在我的项目webServiceClient下的src目录下。最后面跟的是你的webservice的wsdl的uri地址,在上一篇文章中,点击{http://service.cxf.observer.com/}GradeService后出现的地址。在此提醒,在实际的项目开发当中,必须将127.0.0.1:8080换成你的网站域名的地址来生成客户端,因为调用客户端是通过远程来进行的,而127.0.0.1:8080显然只适合在本机使用。在这里因为只是用于本机测试,所以就使用127.0.0.1:8080。
   如果没有出现错误,那么你在你的目录底下就会看到有新的目录生成,你会看到这个新生的目录里面有着各种.java文件,没错,这些就是你使用wsdl2java命令生成的webservice客户端。
第四:简单的使用客户端
   生成客户端之后,将它放到了eclipse里面会看到有错误如下图:
java中webservcie客户端的设计开发与应用_第1张图片

   没关系,我们将错误去了就行了,如下图:
java中webservcie客户端的设计开发与应用_第2张图片

   错误去除了之后就好办了,将服务器部署好,运行,然后调用客户端链接webservice,调用方法如下:

public static void main(String[] args) {
    GradeService_Service gradeService_Service = new GradeService_Service();
    GradeService gs = gradeService_Service.getGradeServicePort();
    String gstr = gs.getGradeName(12120);
    System.out.println(gstr);
}

   当输出is succeed时已经证明调用成功了。
   到此,webservice客户端已经开发完成,到了这里已经可以基本满足工作的需要。

第五:封装客户端
   开发webservice客户端(以下简称客户端)是非常简单的事情,如果没有封装的话,我也当然不想说啥了。
   为什么要封装呢?

要是将自己的客户端封装好,打包成jar包以后,哪个java程序想要使用就直接将jar包拿过去就直接用了,这是不是一件很爽的事情?

二、客户端涉及到各种意外情况的反馈,要是服务器没有运行,客户端就运行了怎么反馈信息呢?要是客户端运行的过程中,服务器关闭了又怎么反馈信息呢?而且各种调用客户端的程序的反馈方式都不一样,怎样才能封装得适合各种程序调用呢?比如说web的反馈方式为jsp,swing反馈方式为JOptionPane.showMessageDialog,android的反馈方式可以为Toast.makeText。

三、没有封装的客户端,在调用时是不会强制性的的要你捕获异常的,要是你直接调用,当哪天服务器关闭了,如果是web就会在浏览器中出现异常错误信息,这显然是非常不友好的表现,而且让程序员容易出现不知名错误的。
   本文使用“类似于单例”+“类似于工厂模式”+“异常处理”来实现封装。之所以说是类似,是因为这里不是单例,只是在封装类中存在着一个静态链接类,之所以不用真正的单例,是因为要将原客户端代码与封装类分离开来,这样可以在wsdl改变时,再次调用wsdl2java命令生成代码,不用改变其他东西。工厂模式也是一样的道理。如果客户端程序员非要调用原客户端代码,这时也可以让其灵活利用。
   首先创建一个异常处理类,我的类如下:

package com.observer.service.manager;
public class ConnectException extends Exception {
    private String title;
    private String details;
    public ConnectException(String title, String details) {
        super();
        this.title = title;
        this.details = details;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getDetails() {
        return details;
    }
    public void setDetails(String details) {
        this.details = details;
    }
    @Override
    public String toString() {
        return "com.observer.service.ConnectException [title=" + title + ", details=" + details
                + "]";
    }
}

   然后serviceManager类,比如我的封装类:GradeServiceManager如下:

import javax.xml.ws.WebServiceException;
    import com.observer.service.GradeService;
    import com.observer.service.GradeService_Service;
    public class GradeServiceManager {
        private static GradeService_Service gradeService_Service = null;
        private static GradeService createGradeService() throws ConnectException{
            try{
                synchronized (Thread.currentThread()) {
                    if(gradeService_Service==null){
                        gradeService_Service = new GradeService_Service();
                    }
                }
            }catch (WebServiceException e) {
                e.printStackTrace();
                throw new ConnectException("连接异常1", "服务器正在维护中,请稍后再试,或者联系服务器维护人员进行处理");
            }
            return gradeService_Service.getGradeServicePort();
        }
      
        public static String getGradeName(long toid) throws ConnectException{
            String gradeName = null;
            try {
                GradeService gs  = createGradeService();
                gradeName = gs.getGradeName(toid);
            } catch (ConnectException e) {
                e.printStackTrace();
                throw e;
            } catch (Exception e) {
                e.printStackTrace();
                throw new ConnectException("连接异常2", "服务器正在维护中,请稍后再试,或者联系服务器维护人员进行处理");
            }
            return gradeName;
        }
    }


   在这里,我的webservice只有getGradeName一个方法,所以就简单的将createGradeService放在一起了,实际应用中如果方法多了,完全可以将createGradeService方法与webservcie中的方法封装开来以供灵活运用。
第六:导出jar包与导进jar包
导出jar包很简单,右键项目——>Export——>JAR file选择好保存的路径与名称,我这里选择为webServiceClient.jar,然后Finish完成。
导进jar包:普通的项目跟平时导进ssh框架一样,这里要讲的是maven中导进jar包。
   maven中导进jar包,个人觉得好使点的有两种方式,一种是将jar包放到maven的库中,然后按普通方式配置pom.xml,另外一种是将jar包放到项目下面的目录下然后在pom.xml中配置。因为这里的jar包不大,而且如果进行分布式开发的话,每个人都必须在自己的maven库中配置并放上这个jar包,所以这里用后一种方式。
   一:将webServiceClient.jar复制到项目下的src/main/webapp/WEB-INF/lib目录下,如果没有lib目录,自己创建一个。
   二:在pom.xml中的标签中加入如下配置:


webServiceClient
webServiceClient
1.0
system
${project.basedir}/src/main/webapp/WEB-INF/lib/webServiceClient.jar

   这里的、webServiceClient.jar都是你的jar包文件名
第七:应用客户端
   到了这里,已经可以说是完成了配置了,接下来我们来点成就感,在servlet、swing、android中应用客户端
   servlet中我们可以直接这样用:

String gradename = null;
try {
    gradename = GradeServiceManager.getGradeName(2323);
} catch (ConnectException e) {
    e.printStackTrace();
    request.setAttribute("massage", e.getDetails());
    request.getRequestDispatcher("/errer.jsp").forward(request, response);
    return;
}

   在swing中我们可以这样用:

String gradename = null;
try {
    gradename = GradeServiceManager.getGradeName(2323);
} catch (ConnectException e) {
    e.printStackTrace();
    JOptionPane.showMessageDialog(this, e.getDetails(), e.getTitle(), JOptionPane.ERROR_MESSAGE);
    return;
}

   在android中我们可以这样用:

String gradename = null;
try {
    gradename = GradeServiceManager.getGradeName(2323);
} catch (ConnectException e) {
    e.printStackTrace();
    Toast.makeText(XXXXX.this, e.getDetails(), Toast.LENGTH_LONG).show();
    return;
}

   当然不管是swing还是android或者web都还有很多用法,自己慢慢鼓捣吧!

   在这里共享一下我的客户端项目(webServiceClient)跟maven的web项目(serviceServletClient)代码:http://down.51cto.com/data/857036

    接下来还有js的webservice客户端的设计开发与应用