WebService构建异构系统通信应用
WebService是用来解决异构系统间的通信问题,很多大型的项目用不同的语言构建,比如C++和JAVA间通信和VB间通信。其中有很多概念需要清楚,SOAP是简单传输对象协议,通
常便于理解可以认为是HTML+XML。WSDL是WebService的部署描述符,通过WSDL可以生成存根和骨架进行WebService应用的构建。遇到过很多朋友在做基于WebService应用时无从下
手,特别是项
目大的时候甚至涉及到夸JVM时搞不清哪些是STUP代理和本JVM。本文针对于大型WebService应有开发模式进行说明。
一、搭建WebService环境
WebService的支持环境很多,本文以阿帕奇的开源环境axis进行讲述。
1、下载axis开源工具包
阿帕奇官网下载axis。
2、将axis解压到tomcat的Webapps目录下
下载完成将其解压到tomcat的Webapps目录下,如图
完成后启动tomcat访问axis目录如图所示:
如果能看到这个界面说明axis环境正确,如若不能看到此界面请参照以上步骤解决。
二、编写WebService服务器端程序
1、服务器端程序编写
我们编写一个求和的服务器端程序,代码如下所示:
public class WebServieceServer
{
public int calculation(int a, int b)
{
int sum = a + b;
return sum;
}
}
程序编写完成后另存为.jws文件并保存到tomcat的Webapps下的axis目录中,如图所示:
2、WSDL观察和描述
这时我们访问WebServiceServer.jsw文件观看其生成的WSDL,如图所示:
点击上图“Click to see the WSDL”观看WSDL部署描述文件
由此可以看出WebService实际上用SOAP协议传递的是一个由DTD约束的XML文档。其中可以看出当请求时候约定了方法名称和参数类型,其实WebService对于大数据的处理速度很慢!
以为SOAP传递的数据越大XML文档就越大这样就存在占用带宽问题,所以速度不会快。在电信行业很多事采用CORB这种体系架构来解决异构系统间得通信,CORB传递时不是XML文档格
式而是二进制数据,这个速度很快,但是CORB对于研发人员编码很困难因为其很复杂开发效率低。
三、编写客户端程序进行异步调用
1、动态WebService调用
动态调用是指动态的生成存根在本地工程中并没有异构系统的存根。这种效率较低也不适合开发大型的WebService应用,相比要简单一些很多研发人员采用这种方式,但建议大家不要采用
这种方式。不是很正规。
将axis的所有.jar文件引入到工程中在这里不再阐述,大家都会了。
编写WebService客户端调用程序,代码如下所示:
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.rpc.ServiceException;
import org.apache.axis.AxisFault;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
public class WebServiceClient
{
private static String endpointAddress = "http://localhost:8080/axis/WebServieceServer.jws?wsdl";
public static void main(String[] args) throws MalformedURLException,
AxisFault
{
Service service = new Service();
try
{
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(new URL(endpointAddress));
Integer result = (Integer) call.invoke("calculation", new Object[] {
1, 1 });
System.out.println("-----WebService 返回结果:" + result + "-------");
}
catch (ServiceException e)
{
e.printStackTrace();
}
}
}
这里值得注意的是大家在引用.jar包的时候千万不要引用错了! 这时我们运行以上代码观看效果:
我们可以看到运行结果正确,是求两个数的和。
2、静态WebService调用
静态调用是指预先生成好WebService的存根,其中生成存根有两种方法再此一次给大家介绍。
很多人在开发时候用Eclipse等工具进行生成存根,那种发发大家可以用但是对于原理全部隐藏了本文讲述利用批处理命令来生成存根。批处理命令如下:
set AXIS_HOME=D:\Program Files\axis-1_4
set CLASSPATH=.;%AXIS_HOME%\lib\axis.jar;%AXIS_HOME%\lib\axis-ant.jar;%AXIS_HOME%\lib\commons-discovery-0.2.jar;%AXIS_HOME%\lib\commons-logging-1.0.4.jar;%AXIS_HOME%\lib\jaxrpc.jar;%AXIS_HOME%\lib\log4j-1.2.8.jar;%AXIS_HOME%\lib\saaj.jar;%AXIS_HOME%\lib\wsdl4j-1.5.1.jar
java org.apache.axis.wsdl.WSDL2Java -p com.learn.webservice http://localhost:8080/axis/WebServieceServer.jws?wsdl
其中AXIS_HOME是自定义的名称用来指定axis的根,类似于配置JAVA环境变量的JAVA_HOME。
最后一行的 http://localhost:8080/axis/WebServieceServer.jws?wsdl是通过HTTP协议在线生成存根,可以用另一种方式就是把WSDL下载到本地保存成一个XML文档,这样做最后一行批处
理命令就变成java org.apache.axis.wsdl.WSDL2Java -p com.learn.webservice D:\\xxx.xml。
编辑好批处理文件后保存为.cmd格式,并且拷贝到工程的SRC目录中。双击运行此时就会生成WebService的存根,如图所示:
其中标红的文件为自动生成的存根文件,我们观看自动生成的WebServieceServerService.java文件。
/**
* WebServieceServerService.java
*
* This file was auto-generated from WSDL
* by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
*/
public interface WebServieceServerService extends javax.xml.rpc.Service
{
public java.lang.String getWebServieceServerAddress();
public com.learn.webservice.WebServieceServer_PortType getWebServieceServer()
throws javax.xml.rpc.ServiceException;
public com.learn.webservice.WebServieceServer_PortType getWebServieceServer(
java.net.URL portAddress) throws javax.xml.rpc.ServiceException;
}
观察此文件是axis生成的一个借口文件,其中就有我们的服务器端程序的得到方法,getWebServieceServer()。
再观察WebServieceServerServiceLocator.java这个程序:
/**
* WebServieceServerServiceLocator.java
*
* This file was auto-generated from WSDL
* by the Apache Axis 1.4 Apr 22, 2006 (06:55:48 PDT) WSDL2Java emitter.
*/
public class WebServieceServerServiceLocator extends
org.apache.axis.client.Service implements
com.learn.webservice.WebServieceServerService
{
public WebServieceServerServiceLocator()
{
}
public WebServieceServerServiceLocator(
org.apache.axis.EngineConfiguration config)
{
super(config);
}
public WebServieceServerServiceLocator(java.lang.String wsdlLoc,
javax.xml.namespace.QName sName)
throws javax.xml.rpc.ServiceException
{
super(wsdlLoc, sName);
}
// Use to get a proxy class for WebServieceServer
private java.lang.String WebServieceServer_address = "http://localhost:8080/axis/WebServieceServer.jws";
public java.lang.String getWebServieceServerAddress()
{
return WebServieceServer_address;
}
// The WSDD service name defaults to the port name.
private java.lang.String WebServieceServerWSDDServiceName = "WebServieceServer";
public java.lang.String getWebServieceServerWSDDServiceName()
{
return WebServieceServerWSDDServiceName;
}
public void setWebServieceServerWSDDServiceName(java.lang.String name)
{
WebServieceServerWSDDServiceName = name;
}
public com.learn.webservice.WebServieceServer_PortType getWebServieceServer()
throws javax.xml.rpc.ServiceException
{
java.net.URL endpoint;
try
{
endpoint = new java.net.URL(WebServieceServer_address);
}
catch (java.net.MalformedURLException e)
{
throw new javax.xml.rpc.ServiceException(e);
}
return getWebServieceServer(endpoint);
}
public com.learn.webservice.WebServieceServer_PortType getWebServieceServer(
java.net.URL portAddress) throws javax.xml.rpc.ServiceException
{
try
{
com.learn.webservice.WebServieceServerSoapBindingStub _stub = new com.learn.webservice.WebServieceServerSoapBindingStub(
portAddress, this);
_stub.setPortName(getWebServieceServerWSDDServiceName());
return _stub;
}
catch (org.apache.axis.AxisFault e)
{
return null;
}
}
public void setWebServieceServerEndpointAddress(java.lang.String address)
{
WebServieceServer_address = address;
}
/**
* For the given interface, get the stub implementation. If this service has
* no port for the given interface, then ServiceException is thrown.
*/
public java.rmi.Remote getPort(Class serviceEndpointInterface)
throws javax.xml.rpc.ServiceException
{
try
{
if (com.learn.webservice.WebServieceServer_PortType.class
.isAssignableFrom(serviceEndpointInterface))
{
com.learn.webservice.WebServieceServerSoapBindingStub _stub = new com.learn.webservice.WebServieceServerSoapBindingStub(
new java.net.URL(WebServieceServer_address), this);
_stub.setPortName(getWebServieceServerWSDDServiceName());
return _stub;
}
}
catch (java.lang.Throwable t)
{
throw new javax.xml.rpc.ServiceException(t);
}
throw new javax.xml.rpc.ServiceException(
"There is no stub implementation for the interface: "
+ (serviceEndpointInterface == null ? "null"
: serviceEndpointInterface.getName()));
}
/**
* For the given interface, get the stub implementation. If this service has
* no port for the given interface, then ServiceException is thrown.
*/
public java.rmi.Remote getPort(javax.xml.namespace.QName portName,
Class serviceEndpointInterface)
throws javax.xml.rpc.ServiceException
{
if (portName == null)
{
return getPort(serviceEndpointInterface);
}
java.lang.String inputPortName = portName.getLocalPart();
if ("WebServieceServer".equals(inputPortName))
{
return getWebServieceServer();
}
else
{
java.rmi.Remote _stub = getPort(serviceEndpointInterface);
((org.apache.axis.client.Stub) _stub).setPortName(portName);
return _stub;
}
}
public javax.xml.namespace.QName getServiceName()
{
return new javax.xml.namespace.QName(
"http://localhost:8080/axis/WebServieceServer.jws",
"WebServieceServerService");
}
private java.util.HashSet ports = null;
public java.util.Iterator getPorts()
{
if (ports == null)
{
ports = new java.util.HashSet();
ports.add(new javax.xml.namespace.QName(
"http://localhost:8080/axis/WebServieceServer.jws",
"WebServieceServer"));
}
return ports.iterator();
}
/**
* Set the endpoint address for the specified port name.
*/
public void setEndpointAddress(java.lang.String portName,
java.lang.String address) throws javax.xml.rpc.ServiceException
{
if ("WebServieceServer".equals(portName))
{
setWebServieceServerEndpointAddress(address);
}
else
{ // Unknown Port Name
throw new javax.xml.rpc.ServiceException(
" Cannot set Endpoint Address for Unknown Port" + portName);
}
}
/**
* Set the endpoint address for the specified port name.
*/
public void setEndpointAddress(javax.xml.namespace.QName portName,
java.lang.String address) throws javax.xml.rpc.ServiceException
{
setEndpointAddress(portName.getLocalPart(), address);
}
}
改程序中实现了我们自定义的服务器端程序, 这时我们别写自己的客户端远程调用程序完成异构系统间的通信。
import java.rmi.RemoteException;
import javax.xml.rpc.ServiceException;
public class WebServiceClient
{
public static void main(String[] args)
{
// WebServieceServerServiceLocator wsl = new WebServieceServerServiceLocator();
WebServieceServerService wsl = new WebServieceServerServiceLocator();
try
{
int sum = wsl.getWebServieceServer().calculation(1, 1);
System.out.println("------WebService result:" + sum + "------");
}
catch (RemoteException e)
{
}
catch (ServiceException e)
{
}
}
}
观察运行结果:
结果正确无误,通过以上讲述我们可以开发出任意的WebService应用。时间仓促文中不免有些问题请朋友们谅解,在这里拜谢各位!!!