精彩的人生

好好工作,好好生活

BlogJava 首页 新随笔 联系 聚合 管理
  147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

#

http://www.yesky.com/SoftChannel/72342371961929728/20030821/1723269.shtml

概述

  本文介绍了一个比较简单实用的基于Java的SOAP引擎——Apache组织推出的Axis——的
安装、配置和应用开发方法,希望对有兴趣做基于Java的Web Services应用开发的朋友有所
帮助。

  Axis简介

  Axis是Apache组织推出的SOAP引擎,Axis项目是Apache组织著名的SOAP项目的后继项目
,目前最新版本是采用Java开发的1.1版本,C++的版本正在开发之中。Axis v1.1软件包可
以从http://ws.apache.org/axis/dist/1_1/下载得到。

  Axis的安装



  应用Axis开发Web Services,你需要有一个支持Servlet的服务器引擎,比如广为人知

的Tomcat(Tomcat也是由Apache组织所提供的,目前的最新版本为4.1.24,下载地址为http

://jakarta.apache.org/builds/jakarta-tomcat-4.0/release/v4.1.24/)。在此之前当然

你机器必须已经装好了JDK1.3以上的版本,当安装好Tomcat之后,只需将下载的Axis软件包
解压缩,将其中的“webapps”目录下的“axis”目录整个拷贝到Tomcat安装目录下的“web
apps”目录下即可。

  Axis的配置

  Axis基于Java开发,可以部署于多种操作系统,使用前需要配置一系列的系统变量,在
此假定你已经在本机上装好了Tomcat 4.0以上的版本,需要配置的系统变量如下表所示:

CATALINA_HOME
C:\Tomcat_4_1

(此处应为Tomcat的安装位置,注意路径名中不要有空格)

AXIS_HOME
%CATALINA_HOME%\webapps\axis

AXIS_LIB
%AXIS_HOME%\lib

AXISCLASSPATH
%AXIS_LIB%\axis.jar;%AXIS_LIB%\commons-discovery.jar; %AXIS_LIB%\commons-logging

.jar;%AXIS_LIB%\jaxrpc.jar; %AXIS_LIB%\saaj.jar;%AXIS_LIB%\log4j-1.2.8.jar; %AXI
S_LIB%\xml-apis.jar;%AXIS_LIB%\xercesImpl.jar


  如果你不愿做这么繁琐的类路径设置,可以直接将axis软件包中“lib”目录下的所有.
jar文件加入到系统环境变量CLASSPATH中即可。

  Axis的测试

  安装配置完毕后,应测试一下是否Axis可以正确运行了。

  启动Tomcat服务器,在浏览器中访问http://localhost:8080/axis/happyaxis.jsp,如
果页面显示有错误,则需要回头检查一下相关配置是否正确,如果浏览页面能正确显示出系
统组件、属性等参数配置信息,则表示安装成功,如下图所示:

  服务的发布

  Axis提供了两种服务发布方式,一种是即时发布(Instant Deployment),一种是定制
发布(Custom Deployment)。

  使用即时发布

  对即时发布的支持是Axis的特色之一,使用即时发布使用户只需有提供服务的Java类的
源代码,即可将其迅速发布成Web服务。每当用户调用这类服务的时候,Axis会自动进行编
译,即使服务器重启了也不必对其做任何处理,使用非常简单快捷。

  使用即时发布首先需要一个实现服务功能的Java源文件,将其扩展名改为.jws(Java W
eb Service的缩写),然后将该文件放到“……\webapps\axis”目录下即可。

  在此给出一个从英里到公里的长度单位转换的服务,其源码如下:

文件Distance.jws

/**

* @author 飞鹰

*/

public class Distance

{

public double convertMile2Kilometre( double mile )

{

//实现英里到公里的距离转换

return mile * 1.609;

}//convertMile2Kilometre()

}/* Distance */


  将其放到“……\webapps\axis”目录,通过访问http://localhost:8080/axis/Distan
ce.jws?wsdl可以看到这个服务的WSDL描述文件,这说明Distance服务被成功发布了。如下
图所示:
使用定制发布

  即时发布是一项令人激动的技术,它使Web服务的开发变得如此简单;然而即时发布并
不总是最好的选择,比如有些应用系统是第三方提供的,我们没有购买源代码,只有.clas
s文件,但我们又希望将这个应用系统的一些功能对外发布成Web服务,使其能够在更大范围
内产生作用,这个时候即时发布技术就无能为力了。此外,即时发布技术并不灵活,无法进
行更多的服务配置,这使得它并不能满足一些特定系统的需求。

  因此,Axis提供了另一种服务发布方式,这就是定制发布。

  在此给出一个从加仑到升的容积单位转换的服务,其源码如下:

  文件Capacity.java

package samples.capacity;


/**

* @author 飞鹰

*/

public class Capacity

{

public double convertGallon2Litre( double gallon )

{

//实现加仑到升的容积转换


return gallon * 4.546;

}//convertGallon2Litre()

}/* Capacity */


  将其编译成.class文件,放置到“……\webapps\axis\samples\capacity”目录下,即
可着手进行发布。

  定制发布不需要构建.jws文件,但必须创建服务发布描述文件deploy.wsdd(Web Servi
ce Deployment Descriptor的缩写),这个文件负责描述服务的名称、入口等信息,其内容
如下:

  文件deploy.wsdd

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

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


<service name="Capacity" provider="java:RPC">

<parameter name="className" value="samples.capacity.Capacity"/>

<parameter name="allowedMethods" value="*"/>

</service>


</deployment>


  将该文件也放到“……\webapps\axis\samples\capacity”目录下,然后可以采用Axi
s提供的一个客户端管理工具——AdminClient来完成服务的定制发布。

  在“……\webapps\axis\samples\capacity”目录下,运行:

java -cp %AXISCLASSPATH% org.apache.axis.client.AdminClient deploy.wsdd


  可以看到以下运行结果:

Processing file deploy.wsdd

<Admin>Doneprocessing</Admin>


  这表明Capacity服务定制发布完成。

  通过访问http://localhost:8080/axis/services/Capacity?wsdl可以看到这个服务的W
SDL描述文件,这说明Capacity服务被成功发布了。如下图所示:


服务的访问

  GET方式的服务访问

  一般的SOAP消息都是采用POST方式实现传递,但也可以通过GET方式来访问。比如以下
给出的一个服务——“HelloWorld”,其源码如下:

文件HelloWorld.jws

/**

* @author 飞鹰

*/

public class HelloWorld

{

public String helloWorld()

{

//在服务器端打印输出

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


//返回相应字符串

return "Hello World!";

}//helloWorld()


}/* HelloWorld */


  这个服务给出一个名位“helloWorld”的无入口参数的操作,返回一个内容为“Hello
World!的字符串”,同时在服务器端打印“Hello World!”,将该文件放到“……\webap
ps\axis”目录下,即可通过GET方法直接访问该服务,访问的地址为http://localhost:808
0/axis/HelloWorld.jws?method=helloWorld,可以看到返回的SOAP信封消息,同时服务器
端给出了相应的显示信息“Hello World!”这表明HelloWorld服务被成功访问了。如下图
所示:



  客户端服务访问编程

  Axis提供了一套API来实现SOAP,从http://localhost:8080/axis/docs/apiDocs/index
.html可以看到Axis的API文档。

  其中,org.apache.axis.client.Call和org.apache.axis.client.Service是两个比较
常用的类,一般的客户端程序欲访问一个Web Service时,都要生成一个客户端的Service对
象和Call对象,在访问服务之前,首先要对Call对象设置相应的参数,包括服务的位置、操
作名、入口参数、返回值类型等,最后调用Call对象的invoke方法访问服务。

  以下给出了一个客户端访问Web服务的例程——AXISTest.java:

  文件AXISTest.java

package axisexercise;


import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encoding.XMLType;


import javax.xml.rpc.ParameterMode;


/**

* @author 飞鹰

*/

public class AXISTest

{

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

{

Service service = new Service();

Call call = ( Call ) service.createCall();



//////////访问即时发布的Distance服务

//设置访问点

call.setTargetEndpointAddress( "http://localhost:8080/axis/Distance.jws" );


//设置操作名

call.setOperationName( "convertMile2Kilometre" );


//设置入口参数

call.addParameter( "op1", XMLType.XSD_DOUBLE, ParameterMode.IN );

call.setReturnType( XMLType.XSD_DOUBLE );

Double d1 = new Double( 190 );


//调用服务

System.out.println( d1 + " 英里相当于 " +

call.invoke( new Object[] {d1} ) + " 公里!" );




//////////访问定制发布的Capacity服务

call = ( Call ) service.createCall();

//设置访问点

call.setTargetEndpointAddress( "http://localhost:8080/axis/services/Capacity" );


//设置操作名

call.setOperationName( "convertGallon2Litre" );


//设置入口参数

call.addParameter( "op1", XMLType.XSD_DOUBLE, ParameterMode.IN );

call.setReturnType( XMLType.XSD_DOUBLE );

d1 = new Double( 10.00 );


//调用服务

System.out.println( d1 + " 加仑相当于 " +

call.invoke( new Object[] {d1} ) + " 升!" );

} //main()

}/* AXISTest */


  编译运行后运行可以看到以下的结果:

  190.0英里相当于305.71公里!

  10.0加仑相当于45.46升!
 
  注意程序在访问即时发布的Distance服务和定制发布的Capacity服务时的不同,前者的
服务访问点地址为http://localhost:8080/axis/HelloWorld.jws,而后者的则为http://lo
calhost:8080/axis/services/Capacity。

  总结

  Web Services是未来网络应用的发展方向,SOAP和WSDL是Web Services的核心协议,Ax
is给出了一个很好的SOAP实现,它使得开发Web Services应用变得轻松而有趣。
posted @ 2006-03-09 11:24 hopeshared 阅读(863) | 评论 (0)编辑 收藏

CSDN - 专家门诊 - Java J2SE / 基础类问题

回复人: panq(漫随天外) ( ) 信誉:100 2001-10-25 13:40:12Z 得分:300

简单对象访问协议(SOAP):
用于Internet上的分布式计算,可以实现跨平台跨编程语言的对象访问和方法调用.
它通过HTTP协议实现参数的传输,同时以特定的XML格式表示参数.这样,只需要一个支持H
TTP协议的WEB服务器和一个XML解析器就可以实现简单的SOAP功能.由于成为了标准,所以
会有越来越多的软件支持它.大家若有兴趣的话可以去看SOAP1.1标准.
同时,还有许多SOAP的开发工具,以简化SOAP的开发.随着这些开发工具的完善,我们
甚至可以不用管具体的SOAP格式就可以开发SOAP应用.
下面以APACHE的SOAP包为例,举个例子:
服务器端的Class:
package samples.soap;
public class SOAPCal {
double rate;
public SOAPCal() {
rate = 8.7;
}
public void setRate(double rate) {
this.rate = rate;
}
public Double calculate(int direction, double value) {
Double retVal;
switch(direction) {
case 0:
retVal = new Double(value * rate);
break;
case 1:
retVal = new Double(value / rate);
break;
default:
retVal = null;
}
return retVal;
}
}
客户端Class:
package samples.soap;
import java.io.*;
import java.util.*;
import java.net.*;
import org.w3c.dom.*;
import org.apache.soap.util.xml.*;
import org.apache.soap.*;
import org.apache.soap.encoding.*;
import org.apache.soap.encoding.soapenc.*;
import org.apache.soap.rpc.*;
public class SOAPCalUser {
public static void main(String[] args) throws Exception {
if (args.length != 3
&& (args.length != 4 || !args[0].startsWith("-"))) {
System.err.println("Usage:");
System.err.println(" java " + SOAPCalUser.class.getName() +
" [-encodingStyleURI] SOAP-router-URL name " +
"(0: dollor to yuan | 1: yuan to dollor) value");
System.exit (1);
}
int offset = 4 - args.length;
String encodingStyleURI = args.length == 11
? args[0].substring(1)
: Constants.NS_URI_SOAP_ENC;
URL url = new URL(args[1 - offset]);
int direction = Integer.parseInt(args[2 - offset]);
double value = Double.parseDouble(args[3 - offset]);
Call call = new Call();
call.setTargetObjectURI("urn:SOAPCal");
call.setMethodName("calculate");
call.setEncodingStyleURI(encodingStyleURI);

Vector params = new Vector();
params.add(new Parameter("direction", int.class, new
Integer(direction), null));
params.add(new Parameter("value", double.class, new Double(value),
null));
call.setParams(params);
Response resp;
try {
resp = call.invoke(url, "");
} catch (SOAPException e) {
System.err.println("Caught SOAPException (" +
e.getFaultCode() + "): " +
e.getMessage());
return;
}
// Check the response.
if (!resp.generatedFault()) {
Parameter ret = resp.getReturnValue();
Object retVal = ret.getValue();
System.out.println(retVal != null ? "\n" + retVal : "I don't
know.");
} else {
Fault fault = resp.getFault();
System.err.println("Generated fault: ");
System.out.println (" Fault Code = " +
fault.getFaultCode());
System.out.println (" Fault String = " +
fault.getFaultString());
}
}
}

package samples.soap;
import java.io.*;
import java.util.*;
import java.net.*;
import org.w3c.dom.*;
import org.apache.soap.util.xml.*;
import org.apache.soap.*;
import org.apache.soap.encoding.*;
import org.apache.soap.encoding.soapenc.*;
import org.apache.soap.rpc.*;

public class SOAPCalAdmin {
public static void main(String[] args) throws Exception {
if (args.length != 2
&& (args.length != 3 || !args[0].startsWith("-"))) {
System.err.println("Usage:");
System.err.println(" java " + SOAPCalAdmin.class.getName()
+ " [-encodingStyleURI] SOAP-router-URL name " +
"rate ");
System.exit (1);
}
int offset = 3 - args.length;
String encodingStyleURI = args.length == 11
? args[0].substring(1)
: Constants.NS_URI_SOAP_ENC;
URL url = new URL(args[1 - offset]);
double rate = Double.parseDouble(args[2 - offset]);
Call call = new Call();
call.setTargetObjectURI("urn:SOAPCal");
call.setMethodName("setRate");
call.setEncodingStyleURI(encodingStyleURI);
Vector params = new Vector();
params.add(new Parameter("rate", double.class, new Double(rate),
null));
call.setParams(params);
Response resp;
try {
resp = call.invoke(url, "");
} catch (SOAPException e) {
System.err.println("Caught SOAPException (" +
e.getFaultCode() + "): " +
e.getMessage());
return;
}
// Check the response.
if (!resp.generatedFault()) {
System.out.println("The rate has been changed.");
} else {
Fault fault = resp.getFault();
System.err.println("Generated fault: ");
System.out.println (" Fault Code = " +
fault.getFaultCode());
System.out.println (" Fault String = " +
fault.getFaultString());
}
}
}
发布用的XML文件dd.xml:
<isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment"
id="urn:SOAPCal">
<isd:provider type="java"
scope="Application"
methods="setRate calculate">
<isd:java class="samples.soap.SOAPCal"/>
</isd:provider>
</isd:service>
这个程序的功能是设置和计算美元/人民币的兑换价格,用
java org.apache.soap.server.ServiceManagerClient
http://sb3server:8080/soap/servlet/rpcrouter deploy dd.xml
把服务器端程序发布到TOMCAT上,然后在客户端用:
java samples.soap.SOAPCalAdmin http://sb3server:8080/soap/servlet/rpcrouter
XX.XX
来设置汇率(1美元兑换多少人民币), 用
java samples.soap.SOAPCalUser http://sb3server:8080/soap/servlet/rpcrouter
(1|0) XX.XX
来换算,其中1和0代表从人民币到美元和从美元到人民币,下一个参数是要换算的钱数.
另外,在http://www.xmethods.com/gettingstarted/apache.html
有一个简单的教程介绍怎样用APACHE的SOAP包写SOAP客户端程序.讲解比较详细.
注意点:
*如果SOAP传回来的参数是一个CLASS,这个CALSS会被序列化(Serializer)为一段XML
代码,在客户端接这个CLASS时,仍然需要一个同名CLASS,而且那些被传递过来的数据的SE
T和GET方法名和参数名要相同.如果是自定义的CLASS,就要做maping声明.声明方法见APA
CHE SOAP包的samples\addressbook\DeploymentDescriptor.xml文件中isd:mappings的
写法.
在客户端调用时要加上
SOAPMappingRegistry smr = new SOAPMappingRegistry();
BeanSerializer beanSer = new BeanSerializer();
smr.mapTypes(/*encodingStyle*/Constants.NS_URI_SOAP_ENC,
new QName(/*Namespace URI*/"urn:xml-soap-address-demo", /*Local
Part*/"address"),
/*Class type*/Address.class, /*java2XMLClassName*/beanSer,
/*xml2JavaClassName*/beanSer);
call.setSOAPMappingRegistry(smr);
*目前不是所有的CLASS都能被序列化,如Hashtable就不行,所以最好用简单的数据类
型,如String,String,Integer,Double及其数组来传递变量,对复杂的参数,可以直接做成
XML Document传递(使用Constants.NS_URI_LITERAL_XML作为EncodingStyleURI),这样就
省得客户端专门做个CLASS来接参数,也方便跨语言的调用.在使用APACHE的SOAP包时,XML
Document在客户端会被转换为XML DOM的Element class.
现在唯一的方法是自己写进行序列化的程序,不过以后也许会有标准的序列化方法.

*CLASS被序列化时CLASS中的静态的变量是不会被加入的来的,这一点要注意.

posted @ 2006-03-09 11:23 hopeshared 阅读(3911) | 评论 (1)编辑 收藏

作者: ZDNet China

现在是钻研专业术语的时候了。我们将谈谈在P2P网
络体系中XML以及其他Web服务的使用情况,并从技术的角度指出尝试将各种“新”技术嫁接
在一起的好处。



从巴赫开始


巴赫——伟大的作曲家——以他的“为了艺术而艺术”而闻名于世。换句话说,他创作音乐
并并不需要特殊的原因或者动机,仅仅是因为他觉得自己需要这么做。

有时候,技术领域也遵循着同样的道路——我们创造并使用新技术仅仅是因为我们觉得我们


需要这么做。当然,在巴赫的年代,不会每年有五千万份广告来告诉他“你需要创作大提琴

协奏曲来紧跟时代”。


把多种技术集合在一起实际上会创造新的技术。例如,电技术加上麦克风和扬声器就导致了
一系列新技术的出现,如电话和收音机;再加上视频技术又出现了更复杂的技术,如电视和
可视电话。那么根据这一原则,Web技术加上P2P会产生更复杂的东东,这些东东或许会派上
用场,那么它们究竟是些什么呢?



Web服务已经P2P了么?

或许Web服务本身就是P2P的。实际上,已经有几篇文章在探讨Web服务与P2P的“收敛(conv
ergence)”。这里的“收敛”指的是Web服务与P2P共同使用。

或许看到这里你会问:“如何在Web服务中利用P2P技术?”呵呵,这个问题的提法本身就不
对。你应该这么问自己:“我如何在我的P2P网络中利用Web服务呢?”



P2P网络

开发者常常把P2P技术称为P2P网络。这是因为“peer”实际上就是网络中的“节点”。由于

P2P是一个高层次的技术,实际的底层网络对这个概念并不重要。尽管实际上,网络常常是T
CP/IP网络,并利用Internet来从一个peer到达另一个peer,如同IP地址中的节点那样。


P2P网络的应用程序导致了若干种类型的应用程序。从即时消息到文件共享以及分布式计算
的每一样事物都用到了P2P概念和技术。和P2P应用程序一样,它们会遇到各种问题,而Web
服务技术可以解决这些问题。



Web服务对P2P的贡献

P2P的一个主要问题就是定位P2P服务以及理解底层通信协议。一般的P2P途径在Internet上
搜索适当的P2P应用程序并安装定制应用程序。在更集成的环境下,常常用客户API或者工具
包提供了封装,也就是隐藏了应用程序协议的细节。


Web服务为定位应用程序提供了UDDI注册服务。每一个注册到UDDI数据库的应用程序都包含
语言(Web Services Description Language ,WSDL)的格式进行标准化的。

WSDL描述指出了访问服务的实际方法和参数。此外,它还提供了可以被服务器识别的传输和
绑定协议。大多数Web服务通过XML和HTTP、用SOAP来绑定Web服务来传输SOAP消息。

简而言之,Web服务技术(无论故意使用还是无意的)可以解决设计、建立和配置P2P应用程

序中的许多常见问题。联合使用XML、SOAP、WSDL、HTTP和UDDI,使用Web服务的P2P应用程
序将会更加标准、更易于访问、更易于理解并更容易集成。

posted @ 2006-03-09 11:20 hopeshared 阅读(735) | 评论 (0)编辑 收藏

作者: 高科华∣来源:Matrix

J2EE 1.4简介
2003年11月24日,J2EE的JCP(Java Community Process)委员会投票一致通过了J2EE 1.4,这是过去两年内发布的第一个主要版本。这个最新版的企业Java标准开放平台增加了许多新的服务,J2EE 1.4 SDK支持这些服务,现在可以下载这个SDK了。这个SDK包括J2EE 1.4 应用服务器、J2SE 1.4.2和J2EE 1.4示例代码。你可以下载整个SDK或单独下载应用服务器或示例代码。
下面的技巧介绍了J2EE 1.4的一些新特点。也包括如何在Solaris、 Windows、 Linux、和 Mac OS X上安装J2EE 1.4 SDK。但是没有完全覆盖这个平台的所有新内容。关于J2EE 1.4新内容的更全面的介绍,请看J2EE v1.4 Application Server Release Notes。
对Web Service的支持
J2EE 1.4最重要、最受争议的特点是对标准的Web Service的端对端的支持。有了J2EE 1.4,现在可以用HTTP之上的SOAP(Simple Object Access Protocol)使得J2EE组件(例如企业Bean和servlet)成为Web Service。
J2EE 1.4要求应用服务器必须遵守WS-I Basic Profile 1.0,这个规范定义了Web service的传输和协议。这使得Web service是可以互操作的。
与J2EE中Web service有关的关键技术如下:
· Web Services for J2EE 1.1。结合单个J2EE技术创建Web service的主要是Web Services for J2EE。它定义了客户端、service端以及容器之间的部署协议。新的部署描述符文件,webservices.xml,为每一种组件定义了部署模式。Web Services for J2EE 还定义了编程模型(JAX-RPC)、 使用JNDI查找提供service的对象、和安全。最后,它还提供了一个新的Handler对象,开发者可以用这种对象阻止和操作SOAP消息。
· JAX-RPC 1.1 (Java API for XML-Remote Procedure Calls)。JAX-RPC是一个标准的远程过程调用接口,它使用XML作为方法调用和返回值的序列化协议。JAX-RPC 把servlet和无状态会话Beans定义为在SOAP和 WSDL (Web Services Description Language)的基础上的XML Web service的service端。Service端是实现了Web service逻辑的软件组件。JAX-RPC 的client接口定义了对Web service的远程调用是如何发生的,以及参数和返回值(包括collection)是如何序列化的。JAX-RPC 1.1 还支持对安全Web services的基于SSL的验证。
· JAXR 1.0 (Java API for XML Registries)。 JAXR 把不同的XML注册表统一到单个模型。程序员可以利用XML注册表发现和查找service,访问它们的内容和元数据。例如,你可以用应用创建工具访问指定服务器上的注册表,找出服务器提供了哪些service,设计SOAP客户端使用其中的一个service。JARX还使得外部Web service客户端可以访问J2EE Web service。
· SAAJ 1.2 (SOAP with Attachments API for Java)。SAAJ用具有MIME附件的SOAP消息处理客户端和Web service之间的SOAP消息传递。MIME附件既可以用来发送文档(对基于文档的Web service而言)又可以用来发送传递大量数据的参数(对 RPC式的Web service)。 SAAJ还为带附件的SOAP消息定义了DOM(Document Object model,文档对象模型)。它允许用户对如何编码SOAP消息进行控制, 为重复或复杂的任务提供了automation hook。
· JAXP 1.2 (Java API for XML Parsing)。这个包统一了解析和处理XML的各种方法。负责解析的类可以在部署时与运行时之间切换。JAXP 1.2包含了SAX 2.0、 DOM Level 2、和XSLT。
Web层增强
不是所有的J2EE 1.4中的Web层增强都与Web service有关。现有的核心技术也得到了更新。
J2EE 1.4中的Web层最大的增强在于JSP 2.0。JSTL(JavaServer Pages Standard Tag Library)提供了范围广泛的通用tag,这些tag极大地方便了Web层的开发。JSTL还定义了新的表达式语言,这种语言可以用来编写存储在任何范围内的Web层JavaBean组件的表达式。下一个技巧说明了如何使用几种这样的tag。
JSP另一个主要的增强是方便地定义定制tag的能力。在JSP 2.0以前的版本中,定义定制tag要求编写实现Tag接口的类。JSP 2.0仍然支持这种方法,但是它还允许用JSP代码片断定义定制tag(在JSP文件中定义),然后在多个地方使用所定义的定制tag。
EJB 2.1
J2EE 1.4的另一个重要特点是EJB 2.1,EJB 2.1提供了几个新的增强。这些包括:
l 无状态会话Bean可以用作Web service端。
l 新的Timer service可以设置成定时调用企业Bean的ejbTimeout()方法。可以用这个service定时调用商业逻辑。
l EJB-QL增加了对结果集排序的ORDER BY子句和新的合计函数(AVG、MAX、MIN、SUM和COUNT)。
l 现在消息驱动的Bean可以接受任何类型的消息,而不只是JMS消息(以前的版本只接受JMS消息)。现在连接器可以直接与MDB通讯,通过适配器把从外部系统传来的消息翻译成对MDB的调用。
企业Java BluePrint for J2EE 1.4
Java BluePrint示例应用是J2EE平台的必要部分。示例应用展示了应用设计和开发的最佳实践,提供了如何使用J2EE技术的例子。J2EE 1.4 SDK开发版本包含了AdventureBuilder,这是新增的J2EE的Web service示例应用。它也包含了原有的Java Pet Store和无线游戏示例应用。
其他变化
J2EE平台其他的一些重要变化包括:
l JACC 1.0(Java Authorization Contract for Containers ):允许自由选择安全和基于角色的授权提供者。
l Java Deployment API 1.1: 独立于服务器的部署工具。
l Java Message Service (1.1) 增强
l J2EE Connectors 1.5:包括了对异步、双向、多线程连接器的完全支持。
l J2EE Deployment 1.1:包括了可代替DTD的用XML模式定义的部署描述符,为了向后兼容保留了DTD.
l J2EE Management 1.0:用Java工具或非Java工具管理企业资源。
l 新版JavaMail (1.3),Java Transaction API (JTA 版本1.01B), 和JDBC 3.0
安装服务器
用J2EE 1.4新的GUI安装程序安装服务器很简单。所支持的操作系统如下:
l Solaris SPARC 8
l Solaris SPARC 9
l Windows 2000 Pro SP3+
l Windows XP Pro SP1+
l Windows 2000 Server SP3+
l Windows Server 2003
l Linux RedHat 8
除了对Linux RedHat的支持以外,只需作很少的修改,甚至不需修改,服务器就能在许多其他的Linux版本环境运行。在Linux上安装的主要要求是J2RE 1.4.1以上的版本。
在所支持的任意一个操作系统上安装服务器的步骤是:
1. 下载适当的软件包(http://java.sun.com/j2ee/1.4/download-dr.html)。
2. 运行下载的可执行程序。
在Macintosh OS X 或Darwin上安装J2EE 1.4 SDK是可能的,尽管没有宣称对它们的支持。要在OS X 或Darwin上安装J2EE 1.4 SDK,你必须有root访问权限,J2RE必须是1.4.1以上的版本。
在OS X 或Darwin上安装J2EE 1.4 SDK的步骤如下:
1. 下载SDK的Linux版本(http://java.sun.com/j2ee/1.4/download-dr.html)。下载的文件将是ELF二进制文件。
2. 用unzip命令行实用程序将压缩文件解压到一个空目录。必须用unzip,用象StuffIt这样的程序是不行的。在提示符(‘$’)后输入:
$ unzip j2eesdk-1_4-dr-linux-eval
3. 开始安装,输入:
$ java -cp package/PackageFormat.jar:. appserv
安装程序会开始安装SDK。如果偶尔不能看到安装时显示的提示,这时可以调整窗口的大小。
4. 安装程序要求输入Java路径时,输入:
/Library/Java/Home
安装程序会给出一个提示信息“server requires JDK 1.4.2. Java 2 version 1.4.1 will work properly”,选择<continue>。
5. 安装程序完成后,还必须做些工作。第一件要做的工作是改变安装目录img/bin的访问权限。输入:
$ chmod a+x /Users/yourname/SUNWappserver/imq/bin
这里yourname是你的用户名。(这假定服务器安装在/Users/yourname。)
6. 最后一步要求root访问权限。服务器在/Library/Java/Home/jre/bin内查找java和javac,这个目录还不存在。你必须创建这个目录,创建这些程序的二进制代码的符号连接。输入:
$ sudo mkdir -p /Library/Java/Home/jre/bin
$ cd /Library/Java/Home/jre/bin
$ sudo ln -s /Library/Java/Home/bin/java java
$ sudo ln -s /Library/Java/Home/bin/javac javac
sudo命令在第一次运行时会要求你输入口令。如果你不是系统管理员,你必须以root身份登录或su到root才能完成这些工作。
7. 安装到此已经完成。启动应用服务器,输入:
$ cd /Users/yourname/SUNWappserver/bin
$ asadmin start-domain

JSTL(THE JAVA STANDARD TAG LIBRARY)
过去几年,我们一直自己编写定制tag实现JSP页面的显示逻辑。已经建立了几个流行的tag库,用来执行迭代、处理XML、调用辅助函数和访问Web层JavaBean。这些库的功能有许多重叠,更主要的是它们互不兼容。
为了解决这个不兼容问题,JCP就一个共用逻辑和现实tag集达成了一致。这些tag通常在创建Web应用的视图时非常有用。这个新的tag集被称之为JSTL(JavaServer Pages Standard Tag Library)。
JSTL不是J2EE 1.4必需的部分,因此,不要求应用服务器供应商对它的支持。然而,Sun的J2EE 1.4 SDK还是包含了JSTL,其他的供应商也很可能支持它。JSTL并不都是新的---J2EE 1.3容器早就有了JSTL 1.0。JSTL 1.1对JSTL进行了升级,以便利用JSP 2.0和J2EE 1.4的新特点。
这个技巧说明了如何使用几个新的JSTL tag。为了使用这些tag,必须了解新的JSP表达式语言(JSP Expression Language,JSP EL)。
JSP表达式语言
JSTL的基本思想是,JSP页面格式化的大多数数据都是JSP Page状态的。这些状态包括:
l page、request、session或application范围的对象。
l Request参数
l JSP隐含对象(例如,pageContext)
l HTTP header、cookie、和request 参数
l Servlet上下文初始化参数
关于JSP页面可以使用的数据的完整列表,请看J2EE 1.4教程(http://java.sun.com/j2ee/1.4/docs/tutorial/doc/JSPIntro7.html)。
用户定义的JavaBean(包括JavaBean和对企业Bean的引用)可以绑定到任何范围的状态变量。如果你在一个页面上用代码片断创建了一个新的Bean,你只需使用<jsp:useBean>tag。否则,只能在EL表达式中用名称访问Bean。JSP 2.0表达式语言使用JavaBean的命名机制操纵所连接的Bean。这个语言也为JSP tag中所用的表达式定义了语法。JSP页面编译器把分隔符${和}之间的JSP语句看成表达式。
解释JSP表达式是如何工作的最容易的方法是用例子,下面我们就看一看这个技巧的示例代码。
示例代码
示例代码是一个使用了两个JavaBean的Web应用。JavaBean ColorScheme是一个映照,这个映照的键名是颜色名称,键值是ColorBean对象。ColorBean有名称(用这个名称注册到ColorScheme),red、green和blue颜色组件。ColorScheme继承了javax.util.TreeMap。对ColorScheme迭代按名称顺序取得它的所有ColorBean对象。ColorBean继承了java.awt.Color,因此,在JSP EL中可以使用它继承的所有方法(包括JavaBean属性)。
应用的欢迎页面,index.jsp,操作有几百个ColorBean对象的ColorScheme对象。这些对象的数据来源于Web归档文件中的文本文件(rgb.txt)。文件中的数据有下面的格式:
R G B Name
240 248 255 AliceBlue
index.jsp前面的一段代码初始化ColorScheme Bean,以名称“scheme”用session状态存储这个Bean,如下所示:
<jsp:useBean id="scheme"
class="com.elucify.tips.dec2003.ColorScheme"
scope="session">

<!-- Initialize this bean -->
<%
// Open a stream to the init file
InputStream stream =
application.getResourceAsStream("/rgb.txt");

// Get a reference to the scheme bean
ColorScheme colorScheme =
(ColorScheme)pageContext.findAttribute(
"scheme");

// Load colors from stream
try {
colorScheme.load(stream);
} catch (IOException iox) {
throw new JspException(iox);
}
%>
</jsp:useBean>

(注意,如果使用tag文件代替代码片断,这个应用会更好。Tag文件是JSP 2.0的新特点,将在以后的使用技巧中介绍。)
上面的代码典型地使用了<jsp:useBean>tag初始化这个tag所创建的Bean。在index.jsp对scheme Bean初始化并把它放在session范围内以后,其他JSP页面就可以对这个scheme Bean的数据进行格式化。
打印ColorScheme集大小的JSP代码可能是下面这个样子:
<%
ColorScheme scheme =
(ColorScheme)session.getAttribute("scheme");
out.println("The current color scheme has " +
scheme.size() + " colors.");
%>
使用JSTL和JSP表达式语言,这个任务会更简单,可读性也更强。示例页面Count.jsp就是这样做的:
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions"
prefix="fn" %>

The current color scheme has ${fn:length(scheme)} colors.

第一行为JSTL函数包中的tag定义了前缀fn(关于这个包的更多信息,请看教程)。第二行是包含了表达式${fn:length(scheme)}的模板文本。JSP页面在运行时用scheme对象的长度代换这个表达式。因为scheme是一个映照,其长度返回的是其中条目的个数。Length函数对所有Collection类型都是可用的。
更有趣的示例是示例页面ListColorNames.jsp,它列出了ColorScheme bean中的所有颜色的名称:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core"
prefix="c" %>

This is a list of the names of all of the colors
in the current color scheme:

<ol>
<c:forEach var="entry" items="${scheme}">
<li>${entry.key}</li>
</c:forEach>
</ol>
行<%@taglib%>定义c为JSTL Core tag的前缀。这个页面的其他部分定义了一个有序列表。使用<c:forEach>对scheme集中的所有条目迭代。所有Collection类都可用ForEach tag。接著把在var属性中给出名称的page变量赋给这个集中的每个值。
当forEach tag的item属性中的表达式的值是java.util.Map时,在var中命名的变量被设置为类型是java.util.Map.Entry的item。这时,迭代变量被称为entry,因此,用表达式${entry.key}取得键名。
在下面的例子中你会看到,可以用表达式${entry.value}得到每个entry的值。这是因为java.util.Map.Entry对象有getKey和getValue方法,表达式语言遵守JavaBean的命名约定。
通常,JSP EL表达式${a.b.c.d}是用代码a.getB().getC().getD()来计算的。这种表达式是对JavaBean属性的相继调用的简化。
示例页面ShowColors.jsp显示了scheme中包含的颜色,如下所示:

This table demonstrates all of the colors
in the current scheme.

<TABLE BORDER="1" BGCOLOR="WHITE">
<TR><TH>Name</TH><TH>Sample Text</TH><TH>Color Swatch</TH>
<TH>Hex Code</TH><TH>Opposite Color</TH></TR>

<!-- Loop over color entries in the scheme -->
<c:forEach var="entry" items="${scheme}">

<!-- Set two variables to improve -->
<!-- readability of HTML below -->
<c:set var="color"
value="${entry.value.rgbHex}"/>
<c:set var="name"
value="${entry.key}"/>

<TR>
<TD>${name}</TD>
<TD><FONT COLOR="${color}">${name}</FONT></TD>
<TD BGCOLOR="${color}">${name}</FONT></TD>
<TD>${color}</TD>
<TD BGCOLOR="${entry.value.rgbComplement}">
${name}</TD>
</TR>

</c:forEach>

如上所示,这个例子使用了<c:forEach>。两个 <c:set> tag 把page属性color和name分别设置到颜色和颜色名称的hex表示。按照JavaBean命名约定,下面的行:
<c:set var="color" value="${entry.value.rgbHex}"/>
等效于Java代码
ColorBean cb = (ColorBean)entry.getValue();
pageContext.setAttribute("color", cb.getRgbHex());
模板文本中使用的color和name变量用来创建JSP页面输出中的table行。不用使用<c:get>tag,因为EL变量的值总是可以作为表达式引用,就象${color}这样。
最后一个示例页面,ColorNameGrid.jsp,给出了JSTL tag更多的用法。它说明了如何使用JSTL tag进行下面的工作:
l 访问request参数
l 用两个不同的方法执行有条件输出
l 使用EL比较和运算
l 使用EL算术函数
ColorNameGrid.jsp以多列的table打印ColorScheme中所有颜色的名称。列数在1到10之间,根据request参数cols确定。如果列数超出了范围就产生错误信息。
ColorNameGrid.jsp的代码如下:
<!-- Initialize local variables -->
<c:set var="cols" value="${param['cols']}"/>
"c:set var="col" value="0"/>

<!-- use the "choose" element to limit -->
<!-- number of columns -->
<c:choose>
<c:when test="${cols > 0 && cols <= 10}">

This is a grid of the names of all of the
colors in the current color scheme:
<p>

<TABLE BORDER="0" BGCOLOR="#404040">
<TR>
<c:forEach var="entry" items="${scheme}">
<c:set var="color" value="${entry.value}"/>

<TD><FONT COLOR="${color.rgbHex}">${entry.key}
</FONT></TD>

<c:set var="col" value="${col+1}"/>

<c:if test="${(col % cols) == 0}">
</TR><TR>
</c:if>

</c:forEach>
</TR>

</TABLE>
</c:when>

<c:otherwise>
<!-- Complain about unreasonable input -->

${cols} is an unreasonable number of columns.
<p>
Click <a href="index.jsp">here</a> to try again.
</c:otherwise>

</c:choose>
第一个<c:set>tag取得request参数cols,把它赋给page属性(属性名也是cols),如下所示:
<c:set var="cols" value="${param['cols']}"/>
(这个页面也可以不用page属性cols,在需要的地方使用${param['cols']}。定义page属性是为了使该页面的可读性更强。)
第二个<c:set>tag用值1对page属性col初始化。这个变量用来分隔列。
<c:choose>tag很象Java中的if-else语句。<c:when>tag就象if and else if语句,<c:otherwise>tag就象最后的else语句。<c:choose>tag包含了一系列的<c:when>tag,每一个<c:when>tag都有一个包含表达式的test属性。第一个<c:when>tag体的test表达式返回true,这个tag体执行后包含在输出中。如果没有一个<c:when>的test表达式返回true,就执行<c:otherwise>tag体,将结果送到输出。
在这个例子中,第一个<c:when>tag的test表达式是逻辑表达式:
<c:when test="${cols > 0 && cols <= 10}">
这里所用的变量cols是在上面讨论的第一个<c:set>tag中定义的page属性。如果所要求的列数在1到10之间,这个页面就会产生一个颜色的table。否则(在<c:otherwise> tag中),这个页面就显示一个提示:
<c:otherwise>
<!-- Complain about unreasonable input -->
${cols} is an unreasonable number of columns.<p>
Click <a href="index.jsp">here</a> to try again.
</c:otherwise>
在第一个<c:when>tag体内的是建table的代码。<c:forEach>tag对table内的所有color迭代,把page属性color赋给ColorScheme中的每个ColorBean:
<c:if test="${(col % cols) == 0}">
</TR><TR>
</c:if>
每个颜色名用它所代表的颜色打印出来,用表达式(${color.rgbHex})从color Bean得到颜色的hex表示。变量col在循环的末尾加1,以便正确分行:
<c:set var="col" value="${col+1}"/>
最后,循环在一行结束时用算术表达式和<c:if>tag强迫分行。
上面的例子仅仅使我们对JSTL tag能做些什么有个初步印象。JSTL tag可以用来处理URL、传递请求、包含其他Web资源的内容、处理XML、创建国际化内容、执行SQL查询,还有很多。利用JSTL提供的强大的新工具可以使JSP的开发更容易。

运行示例代码
下载以上两个技巧的示例代码的归档文件(http://java.sun.com/developer/EJTechTips/download/ttdec2003.war)。应用上下文的root是ttdec2003。下载的war文件还包含了这个示例应用的全部源代码。
你可以用deploytool程序或admin console在J2EE 1.4应用服务器上部署应用归档文件(ttdec2003.war)。你也可以用asadmin命令部署应用,如下所示:
asadmin deploy install_dir/ttdec2003.war
用war文件所在的目录代替install_dir。
可以用http:// ://localhost:8000/ttdec2003访问应用。
对于与J2EE 1.4兼容的其他应用服务器,用你所用的服务器部署工具把应用部署到你的平台上。
你应该在启动应用时看到下面的页面:


posted @ 2006-03-09 11:10 hopeshared 阅读(1062) | 评论 (0)编辑 收藏

在本文寫作時,並無任何 SOAP 實作,能進行作業名稱的多載動作。這對使用 Java 的客戶端是很重要的,因為使用 Java 的伺服端所使用的介面,會利用 Java 的多載功能。但這對使用 COM 的客戶端倒無所謂,因為 COM 並不支援多載。

<binding> 與 <operation> 元素
Binding 區段是,指定通訊協定、序列化、與編碼的地方。若 Types、Messages、與 PortType 等區段負責抽象的資料內容,那麼 Binding 區段便負責處理資料傳輸的具體細節。Binding 區段負責使前三個區段的抽象具體化。

將繫結規格從資料與訊息宣告中分離出來的意義是,執行相同業務的服務提供者,可將一組作業 (portType) 標準化。若欲凸顯自身的差異,每個提供者可另外提供自訂繫結。讓 WSDL 擁有匯入 construct 是有好處的;因為如此一來,即可遠離 Bindings 與 Services 區段,將抽象定義置於自身的檔案中;並可將其散佈於服務提供者間,讓他們把抽象定義設定成標準。例如,銀行可標準化,一組抽象 WSDL 文件詳盡說明的銀行作業。但每家銀行還是可以自由地,「自訂」基礎通訊協定、序列最佳化、與編碼。

下列為 Binding 區段的 WSDL 多載範例,於此重複以方便詳細討論:

<binding name="fooSampleBinding" type="wsdlns:fooSamplePortType">
<stk:binding preferredEncoding="UTF-8" />
<soap:binding style="rpc"
transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="foo">
<soap:operation soapAction="http://tempuri.org/action/foo1"/>
<input name="foo1">
<soap:body use="encoded"
namespace="http://tempuri.org/message/"
encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/" />
</input>
</operation>
<operation name="foo">
<soap:operation soapAction="http://tempuri.org/action/foo2"/>
<input name="foo2">
<soap:body use="encoded"
namespace="http://tempuri.org/message/"
encodingStyle=
"http://schemas.xmlsoap.org/soap/encoding/" />
</input>
</operation>
</binding>

<binding> 元素會有個名稱 (本例中為「fooSampleBinding」),以方便 Services 區段的 <port> 元素參照。它有個參照 <portType> 的「type」屬性,在本例中為「wsdlns:fooSamplePortType」。第二行是 MSTK2 擴充元素 <stk:binding>,它可指定 preferredEncoding,或稱「UTF-8」。

<soap:binding> 元素可指定,使用的樣式 (rpc) 與傳輸。傳輸屬性會參照命名空間,以確定所使用的 HTTP SOAP 通訊協定。

有兩個 <operation> 元素具有相同的名稱「foo」。這兩個作業不同之處在於,兩個不同的 <input> 名稱:「foo1」與「foo2」。在兩個 <operation> 元素中,<soap:operation> 元素的「soapAction」屬性皆相同,都是一個 URI。soapAction 屬性是 SOAP 專屬的 URI,並逐字依 SOAP 訊息使用。以此方式取得的 SOAP 訊息,會有個 SOAPAction 標頭;而且還會以 <soap:operation> 元素中的 URI 為其值。雖然 HTTP 繫結需要 soapAction 屬性,但非 HTTP 繫結則不用。本文刊出時,其用途仍然不明。就本範例而言,它似乎可用來區別兩個不同的「foo」作業。SOAP 1.1 宣稱,soapAction 可用來識別訊息的「目的 (intent)」。它更建議伺服端,可用此屬性路由訊息,而不用剖析整個訊息。實務上,其用途差異很大。<soap:operation> 元素也可以含另一個名為「style」的屬性;若特定作業需要覆寫 <soap:binding> 元素中所指定的樣式,則可使用此屬性。

<operation> 元素所含的 <input>、<output>、與 <fault> 元素,可對應 PortTypes 區段的相同元素。在上例中出現的只有 <input> 元素。在本例中,這三個元素都各有一個選擇性的「name」屬性,可用以區別名稱相同的作業。在範例的 <input> 元素中,有個 <soap:body> 元素,它可指定輸入結果 SOAP 訊息之 <body> 的內容。此元素有下列屬性:

Use
它是用以指定資料採「編碼 (encoded)」或「常值 (literal)」。「常值」的意義是,結果 SOAP 訊息所含資料的格式,完全依照抽象定義 (Types、Messages、與 PortTypes 區段) 的指定規格 。「編碼」的意義是,「encodingStyle」屬性 (參考下文) 會指定編碼方式。
Namespace
每個 SOAP 訊息的主體,都有自己的命名空間,以防止名稱衝突。此屬性所指定的 URI,會逐字使用於結果 SOAP 訊息之中。
EncodingStyle
以 SOAP 的編碼方式而言,URI 的值應該是「http://schemas.xmlsoap.org/soap/encoding」。
文件樣式繫結
在上一區段中,<soap:binding> 元素有個類型屬性被設定成「rpc」。若將此屬性設定成「document」,即可改變訊息在線上的排序。此時這些訊息便成了文件傳輸,而不再是函數簽章。在此繫結類型中,<message> 元素是定義文件格式,而非函數簽章。請參考下例中的 WSDL 片段:

<definitions
xmlns:stns="(SchemaTNS)"
xmlns:wtns="(WsdlTNS)"
targetNamespace="(WsdlTNS)">

<schema targetNamespace="(SchemaTNS)"
elementFormDefault="qualified">
<element name="SimpleElement" type="xsd:int"/>
<element name="CompositElement" type="stns:CompositeType"/>
<complexType name="CompositeType">
<all>
<element name='a' type="xsd:int"/>
<element name='b' type="xsd:string"/>
</all>
</complexType>
</schema>

<message...>
<part name='p1' type="stns:CompositeType"/>
<part name='p2' type="xsd:int"/>
<part name='p3' element="stns:SimpleElement"/>
<part name='p4' element="stns:CompositeElement"/>
</message>
?</definitions>

此結構描述有 SimpleElement 與 CompositeElement 兩個元素,以及一個宣告類型 (CompositeType)。所宣告的唯一 <message> 元素有四個部分 (part):p1 是 CompositeType 類型;p2 是 int 類型;p3 是 SimpleElement;而 p4 是 CompositeElement。下表是四種繫結的比較,依照「使用/類型」分別為:rpc/literal、document/literal、rpc/encoded、與 document/encoded。本表可說明,每種繫結方式反映在線上的實際情況。

rpc / literal
<operation name="method1" style="rpc" ...>
<input>
<soap:body parts="p1 p2 p3 p4"
use="literal"
namespace="(MessageNS)"/>
</input>
</operation>

線上情形:
<soapenv:body... xmlns:mns="(MessageNS)"
xmlns:stns="(SchemaTNS)">
<mns:method1>
<mns:p1>
<stns:a>123</stns:a>
<stns:b>hello</stns:b>
</mns:p1>
<mns:p2>123</mns:p2>
<mns:p3>

<stns:SimpleElement>

123

</stns:SimpleElement>
</mns:p3>
<mns:p4>
<stns:CompositeElement>
<stns:a>123</stns:a>
<stns:b>hello</stns:b>
</stns:CompositeElement>
</mns:p4>
</mns:method1>
</soapenv:body>
document / literal / type=
<operation name="method1"
style="document" ...>
<input>
<soap:body parts="p1" use="literal">
</input>
</operation>

線上情形:

<soapenv:body... xmlns:stns="(SchemaTNS)">
<stns:a>123</stns:a>
<stns:b>hello</stns:b>
</soapenv:body>

rpc / encoded
<operation name="method1" style="rpc" ...>
<input>
<soap:body parts="p1 p2" use="encoded"
encoding=
"http://schemas.xmlsoap.org/soap/encoding/"
namespace="(MessageNS)"/>
</input>
</operation>

線上情形:
<soapenv:body... xmlns:mns="(MessageNS)">
<mns:method1>
<p1 TARGET="_self" HREF="#1"/>
<p2>123</p2>
</mns:method1>
<mns:CompositeType id="#1">
<a>123</a>
<b>hello</b>
</mns:CompositeType>
</soapenv:body>
document / literal / element=
<operation name="method1"
style="document" ...>
<input>
<soap:body parts="p3 p4"

use="literal">
</input>
</operation>

線上情形:

<soapenv:body... xmlns:stns="(SchemaTNS)">
<stns:SimpleElement>

123

</stns:SimpleElement>
<stns:CompositeElement>
<stns:a>123</stns:a>
<stns:b>hello</stns:b>
</stns:CompositeElement>
</soapenv:body>

document / encoded
<operation name="method1"
style="document" ...>
<input>
<soap:body parts="p1 p2" use="encoded"
encoding=

"http://schemas.xmlsoap.org/soap/encoding/"
namespace="(MessageNS)"/>
</input>
</operation>

線上情形:
<soapenv:body... xmlns:mns="(MessageNS)">
<mns:CompositeType>
<a>123</a>
<b>hello</b>
</mns:CompositeType>
<soapenc:int>123</soapenc:int>
</soapenv:body>


<service> 與 <port> 元素
服務即是一組 <port> 元素。每個 <port> 元素,都以一對一的方式,關連一個位置與 <binding>。若有一個以上的 <port> 元素,與相同的 <binding> 關連,便可以使用其它 URL 作為替換。

在 WSDL 文件中,可以有一個以上的 <service> 元素。多個 <service> 元素,可以有許多用途。其中之一便是,根據 URL 的目的地,將傳輸埠群組化。因此,我只要使用另一個 <service>,就可以重新導向所有股票報價要求;而且我的客戶端程式依然可以正常運作,這是因為在這類的服務群組化中,通訊協定完全不會更動其它的服務。多個 <service> 服務的另一個用途是為了,根據基礎通訊協定,對傳輸埠進行分類。例如,可將所有的 HTTP 傳輸埠,置於一個 <service>;所有的 SMTP 傳輸埠置於另一個 <service>。客戶端便可根據它能處理的通訊協定,搜尋相對的 <service>。

<service name="FOOService">
<port name="fooSamplePort" binding="fooSampleBinding">
<soap:address
location="http://carlos:8080/fooService/foo.asp"/>
</port>
</service>

在一份 WSDL 文件中,<service> 的「name」屬性,可區分出個別服務的不同。因為一個服務可能會有幾個傳輸埠,所以傳輸埠也必須有「name」屬性。

總結
本文已經說明了 WSDL 文件最顯著的 SOAP 特色。但應該聲明的是,WSDL 絕不僅只能在 HTTP 上說明 SOAP 而已。在說明 SOAP 上,WSDL 的表達能力絕對足以使用 HTTP-POST、HTTP-GET、SMTP、與其它通訊協定。只要使用 WSDL,不論是程式開發人員或一般使用者,都可輕鬆處理 SOAP。個人深信,WSDL 與 SOAP 的結合,將可引進全新的應用程式類別,以更徹底地利用各種網路服務。

在 WSDL 的命名空間,有各種 XML 元素。下表整理了這些元素、屬性、與內容,以供參考:

元素 屬性 內容 (子項)
<definitions> name
targetNamespace
xmlns (其它命名空間) <types>
<message>
<portType>
<binding>
<service>
<types> (無) <xsd:schema>
<message> name <part>
<portType> name <operation>
<binding> name
type <operation>
<service> name <port>
<part> name
type (空值)
<operation> name
parameterOrder <input>
<output>
<fault>
<input> name
message (空值)
<output> name
message (空值)
<fault> name

message (空值)
<port> name
binding <soap:address>

資源:
WSDL 1.1
SOAP 1.1
XML 結構描述入門
MS SOAP Toolkit 下載網站
IDL 至 WSDL 的轉譯工具
含 WSDL 至 VB 之 Proxy 產生器的免費網路資源
PocketSOAP:SOAP 之相關元件、工具、與原始程式碼


原文地址:http://stu.timeover.net/article.php?articleid=842
posted @ 2006-03-09 10:25 hopeshared 阅读(1221) | 评论 (0)编辑 收藏

仅列出标题
共30页: First 上一页 17 18 19 20 21 22 23 24 25 下一页 Last