Apache Axis用户指南(1)

本文是 Apache Axis 的用户指南的第一部分。
笔者在学习的过程中,作为记录,简单的翻译了一下。笔者已经翻译了 Apache Axis 的安装及应用文档,也谈不上翻译,只是笔者在学习的过程中,将笔者认为重要的部分作为记录,并加以笔者实践的结果。建议在阅读本文之前先阅读 Apache Axis 安装指南。
0. 介绍
SOAP SOAP 是基于 XML 的通信协议和编码格式,它用于交互应用程序通信。现在的版本是 SOAP 1.2 ,但是 SOAP 1.1 版本使用的更加广泛。 SOAP W3C XML 协议工作组管理。 SOAP 被广泛的认为是跨平台、跨语言的计算机应用和 Web Service 的核心。
AXIS Axis SOAP Engine---- 用来构造 SOAP 处理器,例如客户端,服务器端,网管等等。 Axis 是使用 Java 实现的,但是 Axis 提供一个 C++ 的客户端实现。 Axis 不仅仅是一个 SOAP Engine ,它还包括以下内容:
· 独立的服务器
· 可以 plug in servlet engine 中的服务器
· 支持 WSDL
· 根据 WSDL 生成 Java
· 样例程序
· SOAPMonitor
Axis 1.4 的特性如下:
· 兼容 SOAP 1.1/1.2 两个版本
· 灵活的配置和发布
· 支持 JWS
· 支持所有的基本类型,以及类型映射系统
· 自动的 Java Beans 序列化 / 反序列化,包含自定义的 Java 属性 -->XML 元素 / 属性的映射
· 自动的 Java 集合与 SOAP 数组的双向转换。
· 提供 RPC 和基于消息的 SOAP 服务
· 由发布的服务自动生成 WSDL
· WSDL2Java 工具
· Java2WSDL 工具
· 基本的安全扩展,可以集成到 Servlet 2.2 的安全 / 角色中
· 支持面向绘画的服务,通过使用 HTTP Cookie 或者独立于传输的 SOAP Headers
· SOAP with Attachments 规范的初步支持
· EJB 作为 Web Service 来访问
· HTTP Servlet 的传输
· 基于 JMS 的支持
· 独立的服务器版本
· 大量的例子
根据 Apache Axis 安装指南,安装 Apache Axis Apache Tocmat 服务器。运行本文所适用的例子之前,确保 CLASSPATH 包含以下类库:
·       axis-1_2/lib/axis.jar
·       axis-1_2/lib/jaxrpc.jar
·       axis-1_2/lib/saaj.jar
·       axis-1_2/lib/commons-logging.jar
·       axis-1_2/lib/commons-discovery.jar
·       axis-1_2/lib/wsdl4j.jar
·       axis-1_2/ (for the sample code)
·       遵守 JAXP-1.1 XML 解析器,推荐使用 Xerces ,因为在 Apache Axis 测试的时候使用的就是这个解析器
1. 使用 Axis 开发 Web Service
Getting Started
首先来看一个例子 Web Service 客户端程序,它调用 Apache 提供的 Axis 服务器的 echoString 方法:
package samples.userguide.example1;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
public class TestClient {
public static void main(String[] args) {
try {
           String endpoint =
"http://nagoya.apache.org:5049/axis/services/echo";
           Service service = new Service();
           Call call = (Call) service.createCall();
           call.setTargetEndpointAddress(new java.net.URL(endpoint));
           call.setOperationName(new QName("http://soapinterop.org/",
                                       "echoString"));
           String ret = (String) call.invoke(new Object[] { "Hello!" });
           System.out.println("Sent 'Hello!', got '" + ret + "'");
} catch (Exception e) {
           System.err.println(e.toString());
}
}
}
程序首先创建了 Service Call 对象,他们是标准的 JAX-RPC 对象,用来存储关于调用服务的元数据,然后设置了 SOAP 消息目的地的终端节点的 URL ,接着定义了 Web Service 的操作名,最后激活服务,传递一个数组参数 ( 一个字符串 )
可以查看 SOAP 请求消息的结构如下:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <SOAP-ENV:Body>
    <ns1:echoString xmlns:ns1="http://soapinterop.org/">
      <arg0 xsi:type="xsd:string">Hello!</arg0>
    </ns1:echoString>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
字符串参数自动的序列化成 XML ,服务器响应就是一个 String ,我们将它反序列化后并打印出来。
可以使用 tcpmon 或者 SOAP monitor 来查看请求和响应信息。 ( 笔者并没有网络连接,不能连接到 Apache 网站,所以这个例子没有运行成功。 )
命名参数
在上面的例子中,可以看到 Axis 自动的将 XML 编码的参数命名为 arg0,arg1 ,放在 SOAP 消息中。如果想改变这种命名,很简单,在调用 invoke() 方法之前,使用 addParameter 方法对每个参数命名,同时使用 setReturnType 对返回的参数命名,如下所示:
call.addParameter(“testParam”,
org.apache.axis.Constants.XSD_STRING,
javax.xml.rpc.ParameterMode.IN);
         call.setReturnType(org.apache.axis.Constants.XSD_STRING);
进行上述设置后,会将 testParam 这个参数名赋给并且只赋给第一个调用方法的第一个参数。同时还定义了参数的类型 (org.apache.axis.Constants.XSD_STRING) 和这个参数是输入还是输出或者输入输出参数。在本例中是一个输入参数。现在再运行这个程序时,消息如下:
<testParam xsi:type="xsd:string">Hello!</testParam>
”untyped” 服务器互操作
在上面的例子中,强制设置了 invoke() 方法的返回值类型,本来是一个 Object 类型,但是转换为适当的实际类型 --- 例如,我们已经知道 echoString 方法返回一个字符串,那么我们希望调用 client.invoke() 返回一个字符串。我们先来看一下它是如何工作的:
下面是 echoString 的一个响应:
<?xml version="1.0" encoding="UTF-8"?>
 <SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                    xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <SOAP-ENV:Body>
   <ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/">
    <result xsi:type="xsd:string">Hello!</result>
   </ns1:echoStringResponse>
 </SOAP-ENV:Body>
 </SOAP-ENV:Envelope>
其中红色的部分包含了一个类型声明, Axis 使用它来决定将元素的内容反序列化成什么类型的 Java 对象,在本例中将其反序列化成一个 Java String 对象。很多工具将这种 XML 中的显示类型信息叫做自描述。另外,一些工具返回如下的响应:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <SOAP-ENV:Body>
 <ns1:echoStringResponse xmlns:ns1="http://soapinterop.org/">
   <result>Hello, I'm a string!</result>
 </ns1:echoStringResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
它不包含类型的生命,那么 Java 如何将 <result> 中的内容进行反序列化呢?反序列化成什么类型的对象呢?答案就是 metadata ,关于数据的数据。在本例中,我们需要一个对服务的描述来告诉我们期望的返回类型。下面是在 Axis 客户端需要做的:
call.setReturnType( org.apache.axis.Constants.XSD_STRING );
这个方法会告诉 Axis 客户端,如果返回值类型没有被声明,那么就将返回值的 xsi:type 属性定义成预定义的 SOAP String 类型。
另外还可以通过下面的方法设置返回类型的 Java 类:
call.setReturnClass(String.class);
现在,使用 Axis 作为客户端访问 SOAP 服务就介绍完了。总结一下,利用 Axis 作为客户端访问 SOAP 服务的步骤如下:
创建服务终端节点
初始化 Service ,初始化方法:
Service()
Service(EngineConfiguration config)
Service(EngineConfiguration engineConfiguration, AxisClient axisClient)
Service(java.io.InputStream wsdlInputStream, QName serviceName)
Service(Parser parser, QName serviceName)
Service(QName serviceName)
Service(java.lang.String wsdlLocation, QName serviceName)
Service(java.net.URL wsdlDoc, QName serviceName)
初始化 Call ,初始化方法调用 Service 的如下方法:
Call        createCall()
          Creates a new Call object with no prefilled data.
 Call        createCall(QName portName)
          Creates a new Call object - will prefill as much info from the WSDL as it can.
 Call        createCall(QName portName, QName operationName)
          Creates a new Call object - will prefill as much info from the WSDL as it can.
 Call        createCall(QName portName, java.lang.String operationName)
          Creates a new Call object - will prefill as much info from the WSDL as it can.
设置调用的一些参数:
void         addParameter(java.lang.String paramName, QName xmlType, java.lang.Class javaType, ParameterMode parameterMode)
 void       addParameter(java.lang.String paramName, QName xmlType, ParameterMode parameterMode)
 void       setOperationName(QName operationName)
 void       setPortTypeName(QName portType)
 void       setProperty(java.lang.String name, java.lang.Object value)
 void       setReturnType(QName xmlType)
 void       setReturnType(QName xmlType, java.lang.Class javaType)
 void       setTargetEndpointAddress(java.lang.String address)
.......(org.apache.axis.client.Call org.apache.axis.Call javax.xml.rpc.Call 的方法 )
调用 invoke 方法,调用 SOAP 服务
2. 使用 Axis 发布 Web Service
首先看一下下面这个非常简单的类:
public class Calculator {
         public int add(int i1, int i2) {
                   return i1 + i2;
         }
 
         public int subtract(int i1, int i2) {
                   return i1 – i2;
         }
}
如何将这个类可以通过 SOAP 访问呢?方法有很多种,我们通过 Axis 提供的最简单办法来完成:
JWS(Java Web Service) 文件 --- 瞬时部署
Calculator.java 文件拷贝到 <your-webapp-root>/axis/ 目录下,并修改扩展名为 jws ,即拷贝后的文件为 Calculator.jws ,例如笔者拷贝的目录及文件名为 TOMCAT_HOME/webapps/axis/Calulator.jws
接下来就可以通过下面的 URL 访问 Web Service
Axis 将自动的查找文件,编译 java 类,转换成 SOAP 调用。使用下面的客户端程序:
/*
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
package samples.userguide.example2;
 
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.XMLType;
import org.apache.axis.utils.Options;
 
import javax.xml.rpc.ParameterMode;
 
public class CalcClient
{
   public static void main(String [] args) throws Exception {
       Options options = new Options(args);
       String endpoint = "http://localhost:" + options.getPort() +
                         "/axis/Calculator.jws";
       args = options.getRemainingArgs();
       if (args == null || args.length != 3) {
           System.err.println("Usage: CalcClient <add|subtract> arg1 arg2");
           return;
       }
       String method = args[0];
       if (!(method.equals("add") || method.equals("subtract"))) {
           System.err.println("Usage: CalcClient <add|subtract> arg1 arg2");
           return;
       }
       Integer i1 = new Integer(args[1]);
       Integer i2 = new Integer(args[2]);
 
       Service service = new Service();
       Call     call    = (Call) service.createCall();
 
       call.setTargetEndpointAddress( new java.net.URL(endpoint) );
       call.setOperationName( method );
       call.addParameter( "op1", XMLType.XSD_INT, ParameterMode.IN );
       call.addParameter( "op2", XMLType.XSD_INT, ParameterMode.IN );
       call.setReturnType( XMLType.XSD_INT );
       Integer ret = (Integer) call.invoke( new Object [] { i1, i2 });
      
       System.out.println("Got result : " + ret);
   }
}
使用下面的调用来调用 Calculator.jws
G:/jee/eclipse/workspace/AxisUserGuide>java samples.userguide.example2.CalcClien
t -p8080 add 2 5
Got result : 7
 
G:/jee/eclipse/workspace/AxisUserGuide>java samples.userguide.example2.CalcClien
t -p8080 subtract 10 9
Got result : 1
 
G:/jee/eclipse/workspace/AxisUserGuide>java samples.userguide.example2.CalcClien
t -p8080 unknown 1 2
Usage: CalcClient <add|subtract> arg1 arg2
当端口不是 8080 的时候,需要改成自定义的端口。
由于 JWS web 服务是目的在于实现简单的 web 服务。不能使用 package 。当使用 package 的时候,将出现如下的错误:
G:/jee/eclipse/workspace/AxisUserGuide>java samples.userguide.example2.CalcClien
t -p8080 subtract 10 9
Exception in thread "main" AxisFault
 faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
 faultSubcode:
 faultString: java.io.FileNotFoundException: G:/eclipse/workspace/apache-tomcat-
5.5.25/webapps/axis/WEB-INF/jwsClasses/samples/userguide/example2/Calculator.cla
ss ( 指定されたファイルが見つかりません。 )
 faultActor:
 faultNode:
 faultDetail:
        {http://xml.apache.org/axis/}hostname:neusoft-dc6b5f1
3. 自定义部署 介绍 WSDD
使用 JWS 的唯一有点就是简单,但是灵活性很差,不可以进行配置,不能指定自定义类型,不能使用 Handlers ,所以很少使用。
使用部署描述符
为了灵活的使用 Axis ,主要使用其配置的功能,首先应该属性 Axis Web Service Deployment Descriptor(WSDD) 格式。部署描述符包含了需要部署到 Axis 中的内容,也就是说, Axis Engine 需要使用的内容。通常部署一个 Web Service ,那么我们就从基本的服务开始开始了解 wsdd 。首先看下面这个 wsdd 文件:
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
 <service name="MyService" provider="java:RPC">
 <parameter name="className" value="samples.userguide.example3.MyService"/>
 <parameter name="allowedMethods" value="*"/>
 </service>
</deployment>
比较简单,最外层的元素告诉 engine 这是一个 WSDD 部署,同时定义了 java 这个名称空间。接着 service 元素进行实际的 Web Service 的定义。 service 是一个目标链,也就是说它可能包含以下内容中的部分或者全部:请求流、核心处理器 ( 对于服务来说叫做 provider) 、响应流。在本例中, provider java:RPC ,建立在 Axis 中,提示了这是个 Java RPC 服务。实际上处理这个的类是 org.apache.axis.providers.java.RPCProvider 。一些其他的 providers 包括如下:
通过使用一系列的参数来告诉 RPCProvider 它需要实例化的类以及调用的类 ( 例如 samples.userguide.example3.MyService) 。上面例子中的参数分别为指定服务的类、允许通过 SOAP 访问的方法, ”*” 表示所有的方法都可以访问。也可以通过空白或者都好分割的方面名来限制 SOAP 可以访问的方法列表。
4. 高级 WSDD— 指定更多的选项
WSDD 描述符可以包含关于服务的更多的信息,以及其他的部分,例如 Axis 中的 Handlers ,我们将在后面进行介绍。
服务范围
Axis 支持三种范围的服务对象, ”Request” ”Session” ”Application” ,其中 Request Scope 是默认的,为每个 SOAP 请求创建一个新的对象, Session Scope 针对每个允许使用 session 的客户端创建一个新的对象, Application scope 为所有的请求创建一个单例的共享对象。可以通过 <parameter> 指定,例如:
<service name=”MyService” ...>
<parameter name=”scope” value=”value”>
         ...
</service>
使用 AdminClient
使用 AdminClient ,或者说 org.apache.axis.client.AdminClient 类来将 wsdd 文件发送到 Axis 服务器,以便真正的部署服务。如果将 Axis 部署到不是 tomcat 的服务器上的话,需要使用 -p<port> 参数,默认的是 8080 ,一个典型的调用 AdminClient 的方式是:
java org.apache.axis.client.AdminClient deploy.wsdd
<Admin>Done processing</Admin>
这个命令使服务可以通过 SOAP 进行访问,通过运行 Client 类来检查一下:
java samples.userguide.example3.Client –lhttp://localhost:8080/axis/services/MyService “test me!”
You typed : test me!
整个运行过程如下:
如果将 soapmonitor request response 两个 flow 加入到 deploy.wsdd 文件中:
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
 
 <service name="MyService" provider="java:RPC">
 <requestFlow>
      <handler type="soapmonitor"/>
 </requestFlow>
 <responseFlow>
      <handler type="soapmonitor"/>
 </responseFlow>
 <parameter name="className" value="samples.userguide.example3.MyService"/>
 <parameter name="allowedMethods" value="*"/>
 </service>
</deployment>
那么可以通过访问 http://localhost:8080/axis/SOAPMonitor 来查看 SOAP 请求和响应信息:
如果想验证部署的服务已经在运行,可以将其卸载后再重新调用, undeploy.wsdd 的文件内容如下:
<undeployment xmlns="http://xml.apache.org/axis/wsdd/">
 <service name="MyService"/>
</undeployment>
卸载服务的方法和发布服务的方法相同,只是替换 wsdd 文件而已,卸载后再调用服务时,查看发生了什么:
也可以使用 AdminClient 来列出所有发布到服务器上的组件:
D:/axis-1_4>java org.apache.axis.client.AdminClient list
<ns1:deployment xmlns="http://xml.apache.org/axis/wsdd/" xmlns:java="http://xml.
apache.org/axis/wsdd/providers/java" xmlns:ns1="http://xml.apache.org/axis/wsdd/
">
 <ns1:globalConfiguration>
 <ns1:parameter name="sendMultiRefs" value="true"/>
 ......
<ns1:parameter name="attachments.implementation" value="org.apache.axis.attach
ments.AttachmentsImpl"/>
 <ns1:requestFlow>
   <ns1:handler type="java:org.apache.axis.handlers.JWSHandler">
    <ns1:parameter name="scope" value="session"/>
   </ns1:handler>
   <ns1:handler type="java:org.apache.axis.handlers.JWSHandler">
    <ns1:parameter name="scope" value="request"/>
    <ns1:parameter name="extension" value=".jwr"/>
   </ns1:handler>
 </ns1:requestFlow>
 </ns1:globalConfiguration>
 <ns1:handler name="soapmonitor" type="java:org.apache.axis.handlers.SOAPMonitor
Handler">
 <ns1:parameter name="wsdlURL" value="/axis/SOAPMonitorService-impl.wsdl"/>
 <ns1:parameter name="namespace" value="http://tempuri.org/wsdl/2001/12/SOAPMon
itorService-impl.wsdl"/>
 <ns1:parameter name="serviceName" value="SOAPMonitorService"/>
 <ns1:parameter name="portName" value="Demo"/>
 </ns1:handler>
 .......other ns1:handler
 <ns1:service name="AdminService" provider="java:MSG">
 <ns1:parameter name="allowedMethods" value="AdminService"/>
 <ns1:parameter name="enableRemoteAdmin" value="false"/>
 <ns1:parameter name="className" value="org.apache.axis.utils.Admin"/>
 <ns1:namespace>http://xml.apache.org/axis/wsdd/</ns1:namespace>
 </ns1:service>
 .......other ns1:service
 <ns1:transport name="http">
 <ns1:requestFlow>
   <ns1:handler type="URLMapper"/>
   <ns1:handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
 </ns1:requestFlow>
 <ns1:parameter name="qs:list" value="org.apache.axis.transport.http.QSListHand
ler"/>
.......other parameter
 </ns1:transport>
 ......other transport
</ns1:deployment>
在上面的打印的信息中,包含了 services handlers transports 和其它的内容。实际上它就是 server-config.wsdd 文件的内容。我们在稍后会更详细的介绍它。
更多的部署相关 —Handlers Chains 处理器和链
现在介绍一些 Axis 更强大的特性。比方说,想统计一下服务被调用了多少次,那么就是用一个 handler 来完成。在 Axis 包含这样的例子。当需要使用一个如上的 handler 类的时候,首先需要部署 Handler 本身 ( 也就是说在 wsdd 文件中需要对其进行声明 ) ,然后在 service 中使用 handler 的名字,这个名字由你决定。下面是一个 handler wsdd 文件:
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
 
 <!-- define the logging handler configuration -->
 <handler name="track" type="java:samples.userguide.example4.LogHandler">
 <parameter name="filename" value="d:/MyService.log"/>
 </handler>
 
 <!-- define the service, using the log handler we just defined -->
 <service name="LogTestService" provider="java:RPC">
 <requestFlow>
   <handler type="track"/>
 </requestFlow>
 
 <parameter name="className" value="samples.userguide.example4.Service"/>
 <parameter name="allowedMethods" value="*"/>
 </service>
 
</deployment>
第一部分定义了一个 Handler 叫做 ”track” ,实现的类为 samples.userguide.example4.LogHandler 。这个类接受一个参数 filename ,用于将日志信息记录到这个文件中。
然后再 wsdd 重定义了 LogTestService 服务,和第一个例子相似,也是 RPC 服务。不同之处在于 service 元素包含了一个 <requestFlow> 元素,这表示当服务被调用的时候,一些 Handlers 会被提前调用。通过插入一个 track 引用,这样就可以确保在调用服务的时候,每个消息都会被记录。
根据前面的例子,发布服务并调用:
         执行多次调用后,查看 d:/MyService.log 文件的内容,如下所示:
远程管理
默认情况下, Axis 服务器只允许在本机上访问管理请求,如果希望启用远程管理,那么需要设置 AdminService enableRemoteAdmin 属性为 true 。查看 TOMCAT_HOME/webapps/axis/WEB-INF 目录下的 server-config.wsdd 文件,可以看到 AdminService 的部署描述,添加如下的属性:
<service name="AdminService" provider="java:MSG">
 <parameter name="allowedMethods" value="AdminService"/>
 <parameter name="enableRemoteAdmin" value="true"/>
 <parameter name="className" value="org.apache.axis.utils.Admin"/>
 <namespace>http://xml.apache.org/axis/wsdd/</namespace>
 </service>
启用远程管理的话将允许未被授权的访问,如果启用的话,需要确保在配置中添加了安全限制。

 
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值