老榕树建站软件,装修房子图片,男女做羞羞的视频网站,做怎么样的自己的网站本部分是 apache axis 用户指南的第三部分。在 Axis 中使用 WSDL 文件。 10. 使用 WSDL Web Service Description Language 是由 IBM 和 Microsoft 完成的规范#xff0c;并且被很多其他的组织所支持。 WSDK 用于结构化的描述 Web Services 。 Web 服务的 WSDL 是由程序来使用… 本部分是 apache axis 用户指南的第三部分。在 Axis 中使用 WSDL 文件。 10. 使用 WSDL Web Service Description Language 是由 IBM 和 Microsoft 完成的规范并且被很多其他的组织所支持。 WSDK 用于结构化的描述 Web Services 。 Web 服务的 WSDL 是由程序来使用的它包含了服务的接口服务使用的数据类型以及服务的位置。更多的内容可以参考 W3C 的 WSDL 规范。 Axis 通过以下三宗方式来支持 WSDL ¨ 在 Axis 中发布一个服务后用户可以通过标准的 web 浏览器来访问服务的 URL 在后面添加一个 ?WSDL 这样就可以获得自动生成的服务的 WSDL 文件。 ¨ 提供了一个 WSDL2Java 工具用于根据 WSDL 文件生成 Java 代理类和框架类。 ¨ 提供了一个 Java2WSDL 工具用于根据 Java 类构建 WSDL 文件。 ?WSDL 获取服务的 WSDL 文件 当通过 Axis 成功发布一个服务后这个服务和唯一的一个 URL 相关联。对于 JWS 文件来说 URL 就是 JWS 文件本身的路径对于非 JWS 服务来说一般情况下 URL 的格式如下 http://host[:port]/axis/services/service-name 如果可以通过浏览器访问服务的 URL 那么就会看到一个提示消息提示终端节点是一个 Axis 服务那么你应该通过 SOAP 来访问。提示信息如下 service-name Hi there, this is an AXIS service! Perhaps there will be a form for invoking the service here... 然而如果在 URL 后面添加一个 ”?wsdl” 那么 Axis 会自动生成一个服务的 WSDL 文件并在浏览器中以 XML 格式显示如下图所示 WSDL2Java: 根据 WSDL 文件创建 Stubs 、 Skeletons 和数据类型 客户端绑定 Axis 的 WSDL-to-Java 工具的类为 org.apache.axis.wsdl.WSDL2Java 基本调用方式如下 java org.apache.axis.wsdl.WSDL2Java (WSDL-file-URL) 这会为客户端生成必要的绑定这个过程中 Axis 遵守 JAX-RPC 规范。假设执行以下命令 cm %AXIS_HOME%/samples/addr java org.apache.axis.wsdl.WSDL2Java AddressBook.wsdl 这会在 %AXIS_HOME%/samples/addr/AddressFetcher2 目录生成很多类。他们之所以在这里生成是由于这是 WSDL 中声明的 targetNamespace 并且是映射到 Java 的包名。名称空间会在下面进行说明 类型 根据 WSDL 类型生成的 Java 类根据 WSDL 的类型进行命名。一般来说 ( 不是绝对的 ), 这个 java 类会是一个 bean 。例如下面的 WSDL 类型 xsd:complexType namephone xsd:all xsd:element nameareaCode typexsd:int/ xsd:element nameexchange typexsd:string/ xsd:element namenumber typexsd:string/ /xsd:all /xsd:complexType WSDL2Java 会生成如下的 Java 类 public class Phone implements java.io.Serializable { public Phone() {...} public int getAreaCode() {...} public void setAreaCode(int areaCode) {...} public java.lang.String getExchange() {...} public void setExchange(java.lang.String exchange) {...} public java.lang.String getNumber() {...} public void setNumber(java.lang.String number) {...} public boolean equals(Object obj) {...} public int hashCode() {...} } XML--Java 的映射元数据 上面例子中的 XML 类型名为 phone 而生成的 Java 类名为 Phone 第一个字母为大写以适应 Java 编码规范。这种映射经常发生因为对于 XML 的名称或者标志符的限制要比 Java 少得多。例如如果 phone 的子元素的名字为 new 那么由于 new 是 Java 中的保留字所以不能生成这样的成员属性。为了支持这种类型的映射同时支持 XML 属性的序列化与反序列化通过类型元数据系统来关联 Java 数据类和描述符。 当 WSDL2Java 工具生成了一个数据 bean 例如上面的 Phone 类它会观察是否 schema 中包含一些没有直接映射到 Java 的成员变量的属性或者名字。如果有的话就会生成一个静态的代码片断并为这个类提供一个类型描述符。类型描述符是一个变量描述符的集合每一个变量描述符将 Java 的变量映射到 XML 元素或者属性。 // Type metadata private static TypeDesc typeDesc; static { typeDesc new TypeDesc(AttributeBean.class); FieldDesc field; // An attribute with a specified QName field new AttributeDesc(); field.setFieldName(name); field.setXmlName(new QName(foo, nameAttr)); typeDesc.addFieldDesc(field); // An attribute with a default QName field new AttributeDesc(); field.setFieldName(male); typeDesc.addFieldDesc(field); // An element with a specified QName field new ElementDesc(); field.setFieldName(age); field.setXmlName(new QName(foo, ageElement)); typeDesc.addFieldDesc(field); } Holders 这种类型作为输入输出或者输出参数使用。 Java 没有输入输出 / 输出参数的概念。为了实现这种行为 JAX-RPC 指定使用 holder 类。一个 Holder 类似一个简单的 java 类包含了它的一个类型。例如上面例子中的 Phone 类的 holder 类如下 package samples.addr.holders; public final class PhoneHolder implements javax.xml.rpc.holders.Holder { public samples.addr.Phone value; public PhoneHolder() { } public PhoneHolder(samples.addr.Phone value) { this.value value; } } holder 类只有在类型被作为输入输出或者输出参数的时候才被生成。 Holder 类实在类名后面加上后缀 Holder 来命名并且生成到包名为 holders 下面。 PortTypes 服务定义接口 (Service Definition Interface,SDI) 是继承了 WSDL 的 portType 的接口可以通过这个接口访问服务操作。例如下面的 WSDL message nameempty message nameAddEntryRequest part namename typexsd:string/ part nameaddress typetypens:address/ /message portType nameAddressBook operation nameaddEntry input messagetns:AddEntryRequest/ output messagetns:empty/ /operation /portType WSDL2Java 会生成如下的接口 public interface AddressBook extends java.rmi.Remote { public void addEntry(String name, Address address) throws java.rmi.RemoteException; } SDI 接口的名字就是 portType 得名字。为了构造 SDI WSDL2Java 需要从 portType 何 binding 种同时获取信息。 JAX-RPC 规范对这部分的说明是 The name of the Java interface is mapped from the name attribute of the wsdl:portType element. ... If the mapping to a service definition interface uses elements of the wsdl:binding ..., then the name of the service definition interface is mapped from the name of the wsdl:binding element. 这个规范是 JAX-RPC 这意味着只适用于 portType 是一个 RPC 接口。如果绑定的信息不是 RPC 那么将使用绑定的名称。 可以有一个 portType—pt 和两个绑定 bRPC 和 bDoc 这样的话就不能为两个绑定使用一个接口此时需要使用两个接口一个叫 pt 另一个叫 bDoc 同时还要生成两个 stubs 一个叫 bRPCStub( 实现了 pt) 另一个叫 bDocStub( 实现了 bDoc) 。 document/literal 改变了接口的形式。 绑定 Stub 类实现了 SDI Stub 的名字是绑定的名字 Stub 。它包含将方法调用转换成 SOAP 调用的代码通过使用 Axis 的 Service 和 Call 对象。它作为远程服务的代理使调用时就像调用本地对象一样。也就是说不需要处理 endpoing 的 URL 名称空间或者参数数组这些需要通过 Service 和 Call 对象动态调用。 Stub 隐藏了所有这些的具体实现。 根据下面的 WSDL 片段 binding nameAddressBookSOAPBinding typetns:AddressBook ... /binding WSDL2Java 会生成如下的 Stub public class AddressBookSOAPBindingStub extends org.apache.axis.client.Stub implements AddressBook { public AddressBookSOAPBindingStub() throws org.apache.axis.AxisFault {...} public AddressBookSOAPBindingStub(URL endpointURL, javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {...} public AddressBookSOAPBindingStub(javax.xml.rpc.Service service) throws org.apache.axis.AxisFault {...} public void addEntry(String name, Address address) throws RemoteException {...} } Services 服务 正常来讲客户端应用程序不会直接实例化一个 stub 而是实例化一个 service locator 然后调用一个方法来返回 stub 。这个 locator 是根据 WSDL 中的服务元素来指定的。 WSDL2Java 根据 service 元素生成两个独享例如 service nameAddressBookService port nameAddressBook bindingtns:AddressBookSOAPBinding soap:address locationhttp://localhost:8080/axis/services/AddressBook/ /port /service WSDL2Java 会生成如下接口和类 public interface AddressBookService extends javax.xml.rpc.Service { public String getAddressBookAddress(); public AddressBook getAddressBook() throws javax.xml.rpc.ServiceException; public AddressBook getAddressBook(URL portAddress) throws javax.xml.rpc.ServiceException; } 实现了 AddressBookServie 的类 public class AddressBookServiceLocator extends org.apache.axis.client.Service implements AddressBookService { ... } Service 接口定义了 WSDL 中定义的每个接口的 get 方法。 locator 实现了 service 接口也就是说它实现了 get 方法。它用来获取 Stub 实例。 Service 类会默认的创建一个指向 endpoint URL 的 Stub 但是当请求 PortType 的时候可能需要指定一个不同的 URL 。 一个典型的 stub 类的应用如下 public class Tester { public static void main(String [] args) throws Exception { // Make a service AddressBookService service new AddressBookServiceLocator(); // Now use the service to get a stub which implements the SDI. AddressBook port service.getAddressBook(); // Make the actual call Address address new Address(...); port.addEntry(Russell Butek, address); } } 服务器端的绑定 就像在客户端有一个 Web Service 的 Java stub 一样一个 Java 框架的 skeleton 在服务器端使用。为了生成 Skeleton 类需要使用 WSDL2Java 的 —server-side –skeletonDeploy true 选项。例如仍旧使用 AddressBook.wsdl 文件 java org.apache.axis.wsdl.WSDL2Java --server-side --skeletonDeploy true AddressBook.wsdl 可以看到 WSDL2Java 生成了所有在之前生成的 client 端的类但是又声称了一些新的文件 如果不指定 —skeletonDeploy true 选项那么不会生成 skeleton 而是生成的 deploy.wsdd 文件指示实现类已经直接部署了。在这种情况下 deploy.wsdd 文件包含了额外的元数据来描述实现类的操作和参数。通过下面的方法可以直接部署服务 java org.apache.axis.wsdl.WSDL2Java --server-side AddressBook.wsdl 下面是在服务器端生成的文件 绑定 Skeleton 描述 Skeleton 类是介于 Axis engine 和实际的服务实现之间的类。它的名字就是绑定的名字 Skeleton 。例如对于 AddressBook 绑定 WSDL2Java 会生成如下的 Skeleton public class AddressBookSOAPBindingSkeleton implements AddressBook, org.apache.axis.wsdl.Skeleton { private AddressBook impl; public AddressBookSOAPBindingSkeleton() { this.impl new AddressBookSOAPBindingImpl(); } public AddressBookSOAPBindingSkeleton(AddressBook impl) { this.impl impl; } public void addEntry(java.lang.String name, Address address) throws java.rmi.RemoteException { impl.addEntry(name, address); } } 实际的 Skeleton 类可能内容还有很多这里只拷贝了基本的框架。 skeleton 类包含一个 AddressBook 服务的实现。这个实现要么通过构造器传递给 skeleton 要么是一个生成的实现的实例。当 Axis engine 调用 skeleton 的 addEntry 的方法时它只需要简单的将调用分配给实际的实现的 addEntry 方法。 实现模板描述 WSDL 还根据绑定生成了一个实现模板 public class AddressBookSOAPBindingImpl implements AddressBook { public void addEntry(String name, Address address) throws java.rmi.RemoteException { } } 这个类实际上只是一个实现的测试并没有做任何事它预想服务的编程人员来根据这个模板完成具体的实现。 服务 这个工具同时生成了 deploy.wsdd 和 undeploy.wsdd 文件可以供 AdminClient 食用。这些文件只有当填充了实现类的具体方法后编译类文件然后将类文件放到 Axis engine 可以访问的位置后才可以调用 AdminClient 方法来发布服务。 11.Java2WSDL 这个工具笔者就不介绍了 笔者认为使用 WSDL2Java 工具生成的代码中冗余的代码太多并且编码规范有一些 ApacheAxis-Specific 所以觉得还是自己手写代码比较好一些。 一旦写完了 Java 代码可以通过 Web 浏览器访问获取 WSDL 文件没有必要使用 Java2WSDL 了。 12. 公开的 Axis 接口 Axis 公开的接口相对稳定可以使用即使 Axis 重构的话这部分也应该不会修改。或者做一些兼容性的修改。 可以实现的一些 Apache Axis 的接口如下 JAX-RPC 的一些接口这些接口是针对 JAX-RPC 规范 1.0 的会根据新的规范进行修改。 Axis 接口这些相对不稳定。 12. 重要的类 org.apache.axis.MessageContext Axis 所知道的关于请求 / 响应的所有的信息都是通过 MessageContext 来获取的。 Axis 将下面的内容存储在 MessageContext 中 AxisEngine 的引用 请求和响应的消息 (org.apache.axis.Message 对象可以通过 Getter 和 Setter 方法存取 ) 无状态以及服务范围的信息 ( 服务是否维持 session 信息 ) 当前处理状态 认证信息 ( 用户名和密码可以由 servlet 服务器提供或者其他方式 ) 丰富的属性。几乎所有关于属性的信息都可以通过 MessageContext.getProperty() 方法获取。只需要知道属性的名称通常是一个常量定义在例如 org.apache.axis.transport.http.HTTPConstants 这样的类中。例如可以获取 Axis Servlet 的 ServletContext 通过 (HttpServlet)msgC.getProperty(HTTPConstants.MC_HTTP_SERVLET).getServletContext() 。 在服务中当前的 MessageContext 总是可以通过静态的方法 MessageContext.getCurrentContext() 获取。 org.apache.axis.Message org.apache.axis.Message 对象是 Axis 对 SOAP 消息的一种表示。请求和响应消息可以从 MessageContext 中获取 ( 如上所述 ) 。 Message 包括 MIME 头 ( 如果 message 本身包含 MIME 信息 ) 附件 ( 如果 message 本身包含附件 ) SOAPPart( 快速获取 SOAPPart 的 SOAPEnvelope) 可以通过 SOAPPart 访问 SOAP 的任意信息 (soap:Envelope 标签内的任意信息 ) org.apache.axis.SOAPEnvelope 一个 MessageContext 有两个 Message 每个都包含一个 SOAPPart SOAPPart 包含 SOAPEnvelope 。 SOAPEnvelope 包含 SOAP 信封的所有内容。可以从 SOAPEnvelope 中获取 SOAP Header 和 SAOP Body 。 更多内容参考具体的 API 。