WebService发布示例

背景介绍:在多个系统之间交互,WebService使用的频率比较高,现在就用一个简单的示例来看看WebService在不同系统开发时是如何使用的,以及WSDL的使用。

 

WSDL:系统交互,首先必须知道其他系统的WSDL,通过WSDL可以获取到很多东西。那么WSDL是如何生成的呢?生成WSDL也就牵扯到了如何发布一个WebService服务了。那么下面我们就一步一步的来。

 

首先,我们创建一个Web工程,取名WebServiceServer,这里我就创建一个简单的Web工程,并没有选择WebServiceWeb工程。(本示例因为Ecilpse版本缘故,创建的是动态Web工程,这里不做要求)

在工程的src目录下加入代码,一个带返回值的,一个不带返回值的,既然程序员天生喜欢用HelloWorld,那我们也给世界打个招呼吧!

package com.webservice.domain;

 

public class HelloWorld

{

 

    /**

     * 本工程为了方便,就直接使用sysout打印信息,具体的业务逻辑需具情况实现

     * 其实这里最好抽出接口出来,然后在用该类去实现接口

* 这里为了方便,就不使用接口了

     */

 

    public void sayHelloWorld()

    {

        System.out.println("----Hello World----");

    }

 

    public String sayHelloWorld(String somebody)

    {

        if (null != somebody)

        {

            String temp = somebody + "said Hello World!";

            System.out.println(temp);

            return temp;

        }

 

        return null;

    }

}

 

向工程的lib目录下导入如下jar包,并Build到工程中去,jar包版本不一定有要求(activation.jar貌似是重复的哈,不管啦)

 

web.xml配置发布WebService是需要用到的Servlet,代码如下:

Apache-Axis

        

                  org.apache.axis.transport.http.AxisHTTPSessionListener

        

 

        

                   AxisServlet

                   org.apache.axis.transport.http.AxisServlet

        

        

                   AdminServlet

                   org.apache.axis.transport.http.AdminServlet

                   100

        

 

        

                   SOAPMonitorService

                   org.apache.axis.monitor.SOAPMonitorService

                  

                            SOAPMonitorPort

                            5001

                  

                   100

        

 

        

                   AxisServlet

                   /servlet/AxisServlet

        

 

        

                   AxisServlet

                   *.jws

        

 

        

                   AxisServlet

                   /services/*

        

 

        

                   SOAPMonitorService

                   /SOAPMonitor

        

 

        

                   5

        

 

        

                   xsd

                   text/xml

        

Tomcatwebapps目录下新建文件夹WebServiceServer WebServiceServer工程下的WEB-INF目录拷贝到WebServiceServer下,并将WebServiceServer工程编译后的classes目录整个都拷贝到WebServiceServerWEB-INF下。(其实这个步骤就是手动部署一个tomcat应用),当然lib下面有我们刚才上面提到的所有的jar包,classes下面有我们工程编译后的class文件结构目录如下:

 

 

OK,基本工作差不多了,下面我们就启动我们的tomcat,看看我们发布是否成功,如果不出意外的话,应该是不会失败的啦,我们会在IE上看到如下界面:

 

 

好,下面我们继续,下面的内容可能麻烦一些,tomcat可以先不停,IE也用不着关,如果你嫌麻烦呢,可以XX。为了方便呢,我们在我们WebServiceServer工程的WEB-INF下新建一个deploy.wsdd文件,文件格式是xml格式的。内容如下(节点应该比较好理解,至于比较复杂的配置这个就需要另外查资料了,另外deploy.wsdd可以取另外的名字的):

    xmlns="http://xml.apache.org/axis/wsdd/"

    xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">

 

   

   

 

同样,在我们WebServiceServer工程的WEB-INF下新建批处理文件service.bat,内容如下:

java -cp lib/activation-1.1.jar;lib/activation.jar;lib/axis-1.4.jar;lib/commons-discovery-0.2.jar;lib/commons-logging.jar;lib/javamail-1.3.3_01.jar;lib/jaxb-api.jar;lib/jaxb-impl.jar;lib/jaxrpc-1.1.jar/;lib/jaxrpc-api.jar;lib/jaxrpc-impl.jar;lib/jaxws-api-2.0.jar;lib/jstl-1.1.2.jar;lib/log4j.jar;lib/mail.jar;lib/saaj-api-1.3.jar;lib/saaj-impl-1.3.jar;lib/standard.jar;lib/wsdl4j.jar;lib/XmlSchema-1.2.jar org.apache.axis.client.AdminClient -lhttp://localhost:8080/WebServiceServer/services/AdminService deploy.wsdd

其中,-l后的参数是本地要发布WebServiceAdminServlet对应的访问地址

注意:批处理文件里面的内容不可以随便换行,jar包必须跟lib目录下的jar包名字一样,deploy.wsdd必须是我们刚才新建的deploy.wsdd

 

OK,以上步骤如果完成,我们将WebServiceServer工程的WEB-INF下的deploy.wsddservice.bat拷贝到Tomcatwebapps目录下的WebServiceServerWEB-INF下,那么此时,WebServiceServer下的结构就如下了:

 

好,我们刚才tomcat不是没关嘛,如果你关了,嘿嘿,请重新启动你的猫子。启动了之后呢,我们就执行Tomcatwebapps目录下的WebServiceServerWEB-INF下的service.bat,如果该bat文件执行不报错呢,那么在刷新浏览器的话就会出现如下改变:

 

看到没,唉,终于看到希望了,弄了这么长时间,终于给憋出来啦,高兴啊(针对我这样的菜鸟级人物来说的哈,大虾就不要拿你那大钳挥舞摇摆啦,哥怕你那“钢牙”),好,我们点击一下ServiceDemo后面的wsdl连接,就可以看到我们期待已久的WSDL啦,个瘪瘪的。嘿嘿,还有一点让你不敢相信的是,WSDL弄出来了,我们的WebService也就发布成功啦,你要是不信,弄个SoapUI工具,把浏览器上的http://localhost:8080/WebServiceServer/services/ServiceDemo?wsdl这个WSDLSoapUI打开看看就明白啦。

将这个WSDL以文件的形式保存下来,就可以丢给别人用啦。

 

---------------------------------------------------

以下与上面无关,现在可以将你本地的tomcat关掉,然后将webapps下的WebServiceServer这个给干掉啦,以免影响下面的讲解

-------------------------------------------------------

 

好了,任务搞掂一个----------------------------下面继续,如果我们拿到别人给的WSDL文件,怎么用呢,别人在别的地方开发,我们这儿又没外网,怎么连上别人的机器调试我们的代码呢,很痛苦,是不是。嘿嘿,有别人的WSDL就不用皱眉头了撒。

 

拿到WSDL后我们一般会做两件事情,一是生成客户端,这个客户端是用WSDL生成的,我们可以使用里面提供的接口,另外一个是服务器端,这个服务器端很简单哈,一般是用作桩的,是一个假东西,假到什么程度呢,你写的代码我不认,我只要你提供的接口就行啦。OK,一步步来吧。

 

将我们的这个WSDL  http://localhost:8080/WebServiceServer/services/ServiceDemo?wsdl保存为文件的形式,取名helloworld.wsdl。留着,用处大着呢。

 

为了避免新手误会,我们将我们上面贴出来的jarcopy一份出来,随便copy到一个什么目录,比如我们给这个目录取名resources。将我们的helloworld.wsdl也拷贝到这个目录下,另外在这个目录下新建create.bat文件(文件名随便取啦),该bat文件内容如下:

java -cp activation.jar;commons-logging.jar;mail.jar,log4j.jar;wsdl4j.jar;axis-1.4.jar;jaxws-api-2.0.jar;jaxb-api.jar;jaxb-impl.jar;XmlSchema-1.2.jar;commons-discovery-0.2.jar;jaxrpc-api.jar;jaxrpc-impl.jar;jaxrpc-api.jar;jaxrpc-impl.jar;saaj-api-1.3.jar;saaj-impl-1.3.jar;javamail-1.3.3_01.jar org.apache.axis.wsdl.WSDL2Java -s helloworld.wsdl

注意:

1.       bat文件内容不可以随便换行

2.       因为我这个是做例子,所以jar包取的是上面我们创建WebServiceServer时候的jar包,这个bat文件包含的jar包不一定要求跟上面我们创建WebServiceServer时候的jar包版本一致,在不同场合开发,不一定能找到相同版本的jar包,而且我这个例子的版本也不一定非常稳定。一句话:有这么些个名称的jar包就行了,但是bat文件内的jar包名必须跟resources里面的jar包对上号。

好了之后,我们就执行create.bat,执行之后,会生成一个localhost的目录,该目录下面包含了一些代码:

 

咦,看到没,久违的wsdd也出来了。好叻,有了wsddjava文件,我们不是可以用我们最开始讲的模拟一个WebService服务出来嘛。

好,按照文档最开始讲的(这里讲的跟文档最开始讲的有些相同,但并没有任何关系哈,别弄混淆啦,就当WebServiceServer这个工程不存在了,我们现在只是在使用刚才的步骤),一步步来,新建WEB工程(这个WEB工程就是我们以后要用到的模拟桩了,就叫Test),把resources目录下面的包都Build到工程下,然后把localhost的目录下面的所有东西都copysrc下,当然这个时候会出错,因为我们代码放的包不对,代码的package后面有个localhost,而且代码里面也有些地方也有localhost,这个localhost其实是对应到你发布WSDLIP地址的,我们刚才发布的时候用的是localhost对吧,没办法,我们只能采用笨办法,把这些localhost给干掉啦。

去掉这些让人烦心的错误之后,我们就需要写实现了,当然这个实现是模拟的。我们可以看到,HelloWorld.java这个里面提供了2个接口,刚好是我们WebServiceServer提供的两个接口,而HelloWorldService.java则有三个,所以,我们需要实现的是HelloWorld.java这个接口,在这个类名上面按住CtrlT 吧,出来了两个类,一个是ServiceDemoSoapBindingImpl.java,一个是ServiceDemoSoapBindingStub.java,该实现哪个呢,分别打开看一看就知道了,当然是实现 ServiceDemoSoapBindingImpl.java这个撒。

package WebServiceServer.services.ServiceDemo;

 

public class ServiceDemoSoapBindingImpl implements WebServiceServer.services.ServiceDemo.HelloWorld{

    public void sayHelloWorld() throws java.rmi.RemoteException

    {

        System.out.println("I said hello world");

    }

 

public java.lang.String sayHelloWorld(java.lang.String somebody)

throws java.rmi.RemoteException

    {

        System.out.println(somebody + "said hello world");

        System.out.println("shut up!!");

        return "OK";

    }

 

}

再配置web.xml,然后启动tomcat,打开浏览器看是否第一步发布成功,这次就不需要写什么deploy.wsdd,刚才都已经给我们生成好了,就不用在忙乎了,这一步跳过,然后就是执行service.bat,看看服务端是否发布成功啦。这个时候,为了节约时间,我Test工程就没做,所以WSDL还是使用上面那个WSDLhttp://localhost:8080/WebServiceServer/services/ServiceDemo?wsdl。大家要按照具体情况具体去把Test工程的WSDL生成出来啊,我这里是因为时间关系,所以就直接使用最刚才生成好的WSDL

 

 

那么现在呢,我们就做一下客户端,我们就新建一个Java工程,取名ClientDemo

我们将resources文件夹下面的localhost干掉,然后修改create.bat,去掉里面的命令-s,然后执行,又会生成一部分代码

 

再将localhost下面的文件夹及文件都拷贝到ClientDemo工程的src下,并且将我们刚才用到的resources目录下的lib也全部都拷贝到该工程的lib目录下,并且Build到该工程中。我们贴进去的代码肯定是报错了的,我们就不要嫌麻烦,把出错的地方的localhost都去掉吧,当然可能是我生成的WSDL水平太臭啦导致的,所以啊,为了摆脱这样的痛苦,你们加紧儿学吧,再在网上爬爬。

 

修改完成之后呢,我们就可以使用Export命令(ClientDemo工程上点右键就可以看到啦,当然如果你会直接用命令打那更好咯,我这里介绍的是非常非常笨的方法,只适用于菜鸟,不是菜鸟就不用学这个啦)

 

 

 

后面的就NextFinish吧。

 

好,拿到这个jar包,我们就好办了,比如我们现在做的工程中有业务需要调用刚才WebServiceServer那个系统的接口,那么我们就可以用刚才生成的webserviceserver.jar,直接调用里面的接口就OK了。

好,模拟开始   /|/_________________________________________/|/

 

 

新建工程,就当作是另外一个系统吧,比如AgentDemo,其实也就是我们的业务工程(我们的业务需要调用别的系统的接口,因为不同的系统在不同地点开发,因此我们只能调用模拟桩了),上面说的模拟桩工程(就是Test工程),当然这个工程不仅仅要导入webserviceserver.jar,还必须导入resources目录下的所有依赖包,导入之后我们Build一下。

我们编写代码来调用我们别的系统提供给我们的接口吧

package com.webservice.agent;

 

import java.net.MalformedURLException;

import java.net.URL;

import java.rmi.RemoteException;

 

import javax.xml.namespace.QName;

import javax.xml.rpc.ParameterMode;

import javax.xml.rpc.ServiceException;

import javax.xml.rpc.encoding.XMLType;

 

import org.apache.axis.AxisFault;

import org.apache.axis.Constants;

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

 

 

public class CallHelloWorld

{

 

    public static Call getCall()

    {

        Service service = new Service();

        Call call = null;

 

        try

        {

            call = (Call)service.createCall();

            call.setTargetEndpointAddress(new URL("http://localhost:8080/WebServiceServer/services/ServiceDemo?wsdl"));

        }

        catch (ServiceException e)

        {

            e.printStackTrace();

        }

        catch (MalformedURLException e)

        {

            e.printStackTrace();

        }

 

        return call;

    }

 

    /*

     * 调用不带参的sayHelloWorld()方法

     * 因为sayHelloWorld()这个方法在定义时既无返回值也无参数,所以看打印信息必须看tomcat的后台信息了

     */

    public static void callHelloWorld()

    {

        Call call = CallHelloWorld.getCall();

        call.setOperationName(new QName("http://domain.webservice.com", "sayHelloWorld"));

        try

        {

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

        }

        catch (AxisFault e)

        {

            e.printStackTrace();

        }

        catch (RemoteException e)

        {

            e.printStackTrace();

        }

    }

 

    public static void callHelloWorld2()

    {

        Call call = CallHelloWorld.getCall();

        call.setOperationName(new QName("http://domain.webservice.com", "sayHelloWorld"));

        call.addParameter("somebody", XMLType.SOAP_STRING, ParameterMode.IN);

        call.setReturnType(Constants.XSD_STRING);

        try

        {

            String value = (String)call.invoke(new Object[]{"zhangsan"});

            System.out.println(value);

        }

        catch (AxisFault e)

        {

            e.printStackTrace();

        }

        catch (RemoteException e)

        {

            e.printStackTrace();

        }

    }

 

    public static void main(String[] args)

    {

        CallHelloWorld.callHelloWorld();

        CallHelloWorld.callHelloWorld2();

    }

}

 

运行该代码时要保证tomcat是启动的,运行结果会在控制台打印如下信息

 

而且会在tomcat的后台打印如下信息:

 

 

注:当然我这段代码用的是我们文档开头生成的WSDL地址,所以打印的内容是上面显示那样子的,按照正常流程,其实我们应该是将代码中的WSDL地址修改为Test工程(模拟桩工程) WSDL,这样才显得我们不用连别人的系统,连我们做的模拟装就可以跑我们的业务了。

值得说明的是http://domain.webservice.com这个东东在WSDL中可以看到的,其实说白了就是我们在编写wsdd文件时指向的实现类的包路径的倒序。

 

OK,就讲到这儿吧

 

 

 

 

另一种客户端使用方法不用使用Call对象,然后去反射调用申明的接口,可以直接将带Locator的类实例化出来,类似代码如下:

/**

 * 获取UAService_PortType实例

 * @return UAService_PortType对象

 * @see [类、类#方法、类#成员]

 */

public synchronized UAService_PortType getUAServicePortTypeInstance()

{

if (null == uaServicePortType)

{

String wsdlUrl = “wsdl地址”;

UAService_ServiceLocator locator = new UAService_ServiceLocator();

try

{

uaServicePortType = locator.getUAServicePort(new URL(wsdlUrl));

}

catch (MalformedURLException e)

{

logger.excepMethodDebugLog(e);

}

catch (ServiceException e)

{

logger.excepMethodDebugLog(e);

}

}

 

return uaServicePortType;

}

这样就可以使用UAService_PortType类的去调用里面申明的接口了。当然要针对具体情况看locator返回的是什么对象啦,这里仅仅只是给出了一个例子。

第三种方法

 

OmpFacadeLocator locator = new OmpFacadeLocator();

OmpFacadeSoapBindingStub stub = new OmpFacadeSoapBindingStub();

URL url = new URL(pro.getProperty("omp_wsdl_path"));

stub = (OmpFacadeSoapBindingStub)locator.getompFacadePort(url);

使用Locator对象获取stub实例,然后再用stub调用接口

 

 

你可能感兴趣的:(Java基础)