加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

WebService开发工具AXIS指南

发布时间:2020-12-17 01:23:14 所属栏目:安全 来源:网络整理
导读:WebService 开发工具 AXIS 指南 ? ? 本文档是开源文档,你可 以自由使用和传播! ? ? 1 ?????? 介绍 ? Axis ( A pache e X tensible I nteraction S ystem )是一款开源的 WebService 运行引擎,它是 SOAP 协 议的一个实现,其本身来源于 Apache 的另一个项

WebService 开发工具 AXIS 指南

?

?

本文档是开源文档,你可 以自由使用和传播!

?

? 1?????? 介绍

?

Axis A pache eX tensible I nteraction S ystem )是一款开源的 WebService 运行引擎,它是 SOAP 协 议的一个实现,其本身来源于 Apache 的另一个项目 Apache SOAP Axis 分为 1.x 系列和 Axis 2 系列,两个系列体系结 构和使用上有较大的区别,相对而言, Axis1.x 更加稳定,文档也比较齐全,因此本文内容以 Axis 1.x 系列最新版本 1.4 为基础, Axis C++ Java 两个版本的实现,本文描述 Java 版的 Axis

?

采用 Axis 实 现 WebService 时,只需要 POJO 即 可,不要求实现特定的接口或继承特定的父类,不必为提高效率而购买专门的开发工具,在 Eclipse 中开发不需要添加任何插件。

?

Axis 对运行环境的要求是只要支持 Servlet2.3 或以上即可,目前主要的应用服务器都可运行 Axis ,如 Tomcat JBoss Websphere WebLogic Jetty 。并且 Axis 可以很容易和应用程序整合 在一个 Web 应用中,将应用程序的功能展示为 WebService

?

此外, Axis 的 另一个好处就是不用和某个应用服务器绑定在一起,具有很好的可移植性,除配置文件可能要作小的修改外,服务的实现代码不需要做任何修改。

?

Axis 官方网站为 http://ws.apache.org/axis

?

?

2?????? 环境配置

本文例子代码运行环境要求如下:

Windows XP SP2 中文版, JDK1.4 或以上, Apache Axis1.4 Tomcat 4.1 或其他任何支持 Servlet2.3 的应用服务器,本文以 Tomcat 4.1 为例, Java 开发工具为 Eclipse3.1

?

如果还没有安装 JDK http://java.sun.com/javase 下载并安装到本地硬盘,以下用 JAVA_HOME 表示 JDK 安装在本地的路径。

?

http://ws.apache.org/axis 下载 Axis1.4 ,安装包是一个压缩文件,不用安装程序,直接解压到本地硬盘即可。以下用 AXIS_HOME 表示 axis 解压到本地的路径。

?

http://tomcat.apache.org 下载 Tomcat 4.1 安装包,按 Tomcat 安装指南安装到本地,以下用 TOMCAT_HOME 表示 Tomcat 安装在本地的路径。安 装完成后验证安装正确,缺省情况下输入 http://localhost:8080 可进入 Tomcat 页面。

?

下面在 Tomcat 中增加一个 Web 应用,并为其增对 Axis 支 持:

TOMCAT_HOME/webapps 下创建一个新目录 myservices ,然后将 AXIS_HOME/webapps/axis 目录下的文件和子目录都复制到 myservices 目录下。并将 AXIS_HOME/lib/axis-ant.jar 也复制到 myservices/WEB-INF/lib 目录下,该 jar 文 件提供对 ant 脚本的支持。

?

启动 Tomcat ,然后在浏览器中输入 http://localhost:8080/myservices ,如果能显示下面的页面,则表示 axis 已 成功安装到 myservices 应用中,下面创建的 WebService 都在该应用中运行。

?

?

进一步点击 Validation 可以显示运行环境信息,点击 List 可以列出 Axis 自带的两个 WebService 以后增加的 WebService 也显示在这里。

?

以下代码在 Eclipse 中开发,为此在 Eclipse 创建一个 java 项目,名称为 axis-guide ,并将 Axis 的包加到项目的 java build path 中,如下图所示: Axis 这 些包位于 Web 引用 myservices WEB-INF/lib 目录下。


?

3?????? 第一个 WebService

3.1??? 服务端

准备好运行环境后,下面就开始开发 WebService ,该 WebService 名为 EchoService ,有一个方法 echo , 获得一个输入信息后,加入附加信息返回给调用者。原代码如下:

EchoService.java

?

package chen.axisguide.ch3;

?

public class EchoService {

??????

?????? public String echo(String msg) {

?

????????????? return "your input message is " + msg;

?????? }

}

?

?

可以看到该类是一个 POJO ,不需要其他任何附加说明来表明其是一个 WebService 实现。

?

为了让 Axis 能识别服务,需要为服务提供一个描述文件,通常文件名为 deploy.wsdd ,因为该文件用于将服务部署到 Axis 引 擎所在的 Web 应用中。 deploy.wsdd 文件格式为 xml 格 式, EchoService deploy.wsdd 内容如下:

?

?

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

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

???????????

??? <service name="EchoService" provider="java:RPC" >

?????? <parameter name="className" value="chen.axisguide.ch3.EchoService" />

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

??? </service>

?

</deployment>

?

?

service 节点的 name 属性定义服务的名字,在 客户端访问时会用到该名字, provider 中定义 WebService 的提供方式 为 RPC

第一个 parameter 用来描述服务实现类的类名,包括包名。第二个 parameter 参数描述类中哪 些方法可以暴露为 WebService 方法,这里用 * 表示全 部方法。

?

如果要卸载一个已部署的 WebService ,需要提供一个卸载描述文件,用 Axis 提 供的工具读取该文件来卸载已部署的 WebService 上述 deploy.wsdd 对应的卸载 文件为 undeploy.wsdd ,内容如下:

?

?

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

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

???????????

??? <service name="EchoService"/>

???

</undeployment>

?

?

deploy.wsdd undeploy.wsdd 和原代 码 EchoService.java 位于同一个目录中。

?

在项目 axis-guide 的根目录下创建一个 Ant build.xml 来执行编译和部署任务。目录结构如下图所示:

?

?

build.xml 内容如下:

?

<?xml version="1.0" encoding="utf-8"?>

<project name="myservice" default="deployws">

?????? <!-- If your Tomcat installation folder is another,replace below with yourself -->

?????? <property name="web.home" location="C:/Tomcat4.1/webapps/myservices" />

?????? <property name="webclass.dir" location="${web.home}/WEB-INF/classes" />

?????? <property name="weblib.dir" location="${web.home}/WEB-INF/lib" />

?????? <property name="src.dir" location="src" />

??????

?????? <path id="lib.class.path">

???????????????????? <fileset dir="${weblib.dir}">

??????????????????????????? <include name="**/*.jar"/>

???????????????????? </fileset>

?????????????

?????? </path>

??????

?????? <taskdef name="axis-admin" classname="org.apache.axis.tools.ant.axis.AdminClientTask">

????????????? ??????? <classpath refid="lib.class.path"/>

?????? </taskdef>

??????

??????

?????? <target name="compile">

????????????? <javac srcdir="${src.dir}" destdir="${webclass.dir}" source="1.4" compiler="javac1.4" debug="on">

???????????????????? <classpath>

???????????????????? ??????? <path refid="lib.class.path"/>

???????????????????? </classpath>

???????????????????? <exclude name="**/*Test.java" />

????????????? </javac>

?????? </target>

??????

?????? <target name="deployws" depends="compile">

????????????? <axis-admin url="http://localhost:8080/myservices/servlet/AxisServlet"

???????????????????? xmlfile="${src.dir}/chen/axisguide/ch3/deploy.wsdd"/>

?????????????

?????? </target>

??????

?????? <target name="undeployws">

????????????? <axis-admin url="http://localhost:8080/myservices/servlet/AxisServlet"

???????????????????? xmlfile="${src.dir}/chen/axisguide/ch3/undeploy.wsdd"/>

?????? </target>

??????

</project>

?

?

task-def 定义了一个名为 axis-admin 的任务,该任务负责根据 deploy.wsdd undeploy.wsdd 来部署 或卸载 WebService 。此任务的实现类 org.apache.axis.tools.ant.axis.AdminClientTask 位于 axis-ant.jar 文件中。

?

服务实现类原代码编译后的 .class 文件放在 myservices/WEB-INF/classes 目录下,在 build.xml compile 任务中实现。

?

Eclipse 环境中用 Ant 运行该 build.xml ,执行成功后 在浏览器中输入 http://localhost:8080/myservices/servlet/AxisServlet ,可以看到如下的页面,表示 EchoService 已部署成功。

?

?

?

3.2??? 客户端

WebService 部署成功后,下面开发客户端去调用 WebService 的方法,打印返回结果。

?

Client.java

?

package chen.axisguide.ch3;

?

import java.rmi.RemoteException;

?

import javax.xml.rpc.ParameterMode;

import javax.xml.rpc.ServiceException;

?

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encoding.XMLType;

?

?

/**

? * 访问 EchoService 的客户端

? *

? *

? */

public class Client {

?

?????? /**

?????? ? * @param args

?????? ? * @throws ServiceException

?????? ? * @throws RemoteException

?????? ? */

?????? public static void main(String[] args) throws ServiceException,RemoteException {

????????????? // wsdl address 节点的 location 属性

????????????? String endpoint = "http://localhost:8080/myservices/services/EchoService";

????????????? // 要调用的方法名

????????????? String method = "echo";

?????????????

????????????? Service service = new Service();

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

????????????? // 设置客户端访问的远程端点

????????????? call.setTargetEndpointAddress(endpoint);

????????????? // 设置输入参数类型

????????????? call.addParameter("p1",XMLType.XSD_STRING,ParameterMode.IN);

????????????? // 设置返回值类型

????????????? call.setReturnType(XMLType.XSD_STRING);

?????? ??????

????????????? // 输入参数值

????????????? String msg = "call from java";

????????????? // 调用远程方法

????????????? String result = (String)call.invoke(method,new Object[]{msg});

?????????????

????????????? System.out.println(result);

?

?????? }

??????

}

?

确认 Tomcat 已启动,在 Eclipse 环境中运行 Client ,如果没有错误,在控制台将会打印从 EchoService echo 方法获得的结果。

?

客户端访问 WebService 的主要步骤包括:

l ???????? 创建 Call 对象,设置 WebService 的访问端点;

l ???????? 注册序列化和反序列对象,详见下节;

l ???????? 设置访问方法的参数类型以及返回值类型;

l ???????? 初始化参数值;

l ???????? 调用 WebService 的方法,获得 返回结果。

?

JAX-RPC 规范中定义了三种访问服务端的方法:

1. ???????? 在客户端生成远程服务端的静态代理文件,编译后提供给客户端访问服务使用, Axis 提供了工具可根据服务的 wsdl 生 成静态代理文件。但这种方法会在客户端增加若干附加文件,服务端接口发生变化时需要重新在客户端生成文件。

2. ???????? 根据服务端接口文件访问服务。这种方法要求服务实现一个接口,并且该接口要从 java.rmi.Remote 扩展,客户端通过获得该接口的代理来访问服务。这种方法需要在客户端保存一个服务的接口文件。

3. ???????? 动态调用接口。客户端只须通过服务端口、访问方法名和参数类型即可访问服务的方法。访问方式类似于用 反射来调用类方法。这种方法的客户端和服务端的耦合度比前两种要低,上面 Cilent.java 用的就是这种方法。 后面的例子也都采用这种方式访问服务端。

?

4?????? 序列化

Axis 中客户端和服务器端之间的消息使用 SOAP 封 装, java 程序中的数据需要序列化后保存在 XML 文 档中通过网络传输到接收方,接收方从 XML 文档中反序列化为 java 虚 拟机可识别的数据对象。对 java 基本类型, Axis 提 供了默认的序列化和反序列化功能,不需要特别申明即可使用。对自定义类型,如果是 JavaBean ,则可用 beanMapping wsdd 文件中申明该类型所需要的 序列化和反序列化器即可。 Axis 已自带 JavaBean 的序列化和反序 列化功能。 如果 Axis 自带的序列化和反序列化器 不能对自定义对象进行序列化处理,你可以自定义序列化和反序列化器,然后用 typeMappping wsdd 文件中申明即可。

Axis 中, xml 数据类型和 java 类 型之间的映射关系如下:

XML 类 型

java 类 型

xsd:base64Binary

byte[]

xsd:boolean

boolean

xsd:byte

byte

xsd:date

java.util.Date

xsd:dateTime

java.util.Calendar

xsd:decimal

java.math.BigDecimal

xsd:double

double

xsd:float

float

xsd:hexBinary

byte[]

xsd:int

int

xsd:integer

java.math.BigInteger

xsd:long

long

xsd:QName

javax.xml.namespace.QName

xsd:short

short

xsd:string

java.lang.String

?

下面的例子中服务器端向客户端返回一个列表,列表中包含自定义的 Book 对象。

服务实现代码如下:因为只是说明对象的序列化方式,因此就直接创建 对象放入列表对象中,没有从数据库中搜索数据。

LibraryService.java :对象序列化服务端代码

?

package chen.axisguide.ch4;

?

import java.util.ArrayList;

import java.util.List;

?

public class LibraryService {

??????

?????? // 返回一个包含 Book 对象的列表

?????? public List query(String keyword) {

?

?????????????

????????????? Book book1 = new Book();

????????????? book1.setAuthor("Jack Johnson");

????????????? book1.setContent("about java development.");

????????????? book1.setIsbn("123-456-789");

????????????? book1.setName("Java deplopment handbook");

?????????????

????????????? Book book2 = new Book();

????????????? book2.setAuthor("Kim Kent");

????????????? book2.setContent("about ruby development.");

????????????? book2.setIsbn("123-654-897");

????????????? book2.setName("ruby deplopment handbook");

?????????????

????????????? List res = new ArrayList();

????????????? res.add(book1);

????????????? res.add(book2);

?????????????

????????????? return res;

?????????????

?????? }

}

?

服务端代码中不需要对序列化做特殊处理。

?

Book 的定义如下:

Book.java

?

package chen.axisguide.ch4;

?

public class Book {

?????? private String isbn;

?????? private String name;

?????? private String author;

?????? private String content;

??????

?????? public String getAuthor() {

????????????? return author;

?????? }

?????? public void setAuthor(String author) {

????????????? this.author = author;

?????? }

?????? public String getContent() {

????????????? return content;

?????? }

?????? public void setContent(String content) {

????????????? this.content = content;

?????? }

?????? public String getIsbn() {

????????????? return isbn;

?????? }

?????? public void setIsbn(String isbn) {

????????????? this.isbn = isbn;

?????? }

?????? public String getName() {

????????????? return name;

?????? }

?????? public void setName(String name) {

????????????? this.name = name;

?????? }

??????

??????

}

?

?

?

序列化的处理在服务部署文件中定义:

deploy.wsdd LibraryService 描述 文件

?

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

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

???????????

??? <service name="LibraryService" provider="java:RPC" >

?????? <parameter name="className" value="chen.axisguide.ch4.LibraryService" />

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

??? ?????????????

?????? <beanMapping qname="myNS:Book" xmlns:myNS="LibraryService" languageSpecificType="java:chen.axisguide.ch4.Book"/>

??? </service>

?

</deployment>

?

?

beanMapping 节点定义了 Book 对 象的序列化和反序列化使用 Axis 自带的针对 JavaBean 的序列化和反序列化器来实现。

其中, xmlns 定义命名空间为 LibraryService ,和服务同名, qname 定 义为命名空间 myNS 中的 Book ,与被序列化的类名相同, 这种命名方式可使处理的对象一目了然。当然也可命名为其他名字。

?

下面看一下客户端代码中对序列化的处理。

Cilent.java :访问 LibraryService 客 户端代码。

?

package chen.axisguide.ch4;

?

import java.rmi.RemoteException;

?

import javax.xml.namespace.QName;

import javax.xml.rpc.ParameterMode;

import javax.xml.rpc.ServiceException;

?

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

import org.apache.axis.encoding.XMLType;

?

/**

? * 访问 LibraryService 的客户端

? *

? *

? */

public class Client {

?

?????? /**

?????? ? * @param args

?????? ? * @throws ServiceException

?????? ? * @throws RemoteException

?????? ? */

?????? public static void main(String[] args) throws ServiceException,RemoteException {

????????????? // wsdl address 节点的 location 属性

????????????? String endpoint = "http://localhost:8080/myservices/services/LibraryService";

????????????? // 要调用的方法名

????????????? String method = "query";

?????????????

????????????? Service service = new Service();

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

????????????? // 设置客户端访问的远程端点

????????????? call.setTargetEndpointAddress(endpoint);

?????????????

????????????? QName qn = new QName("LibraryService","Book");

?????? ??? call.registerTypeMapping(Book.class,qn,

?????? ????????????????????? new org.apache.axis.encoding.ser.BeanSerializerFactory(Book.class,qn),???????

?????? ????????????????????? new org.apache.axis.encoding.ser.BeanDeserializerFactory(Book.class,qn));

?????? ???????

?????????????

????????????? // 设置输入参数类型

????????????? call.addParameter("p1",ParameterMode.IN);

????????????? // 设置返回值类型

????????????? call.setReturnType(XMLType.XSD_ANYTYPE);

?????????????

????????????? // 输入参数值

????????????? String msg = "key word";

????????????? // 调用远程方法

????????????? Object[] result = (Object[])call.invoke(method,new Object[]{msg});

?????????????

????????????? for(int i = 0; i < result.length; i++) {

???????????????????? Book bk = (Book)result[i];

???????????????????? System.out.println("ISBN: " + bk.getIsbn() + " Book Name: " + bk.getName());

????????????? }

?

?????? }

??????

}

?

在客户端,首先为 Book 定义一个 QName 对象,构造函数中的第 一个参数值要和 wsdd beanMapping 节点的 xmlns:myNS 属性值相同,第二个参数值要和 beanMapping qname 属性值相同。然后在 Call 对象中注册自定义类型所用的序列化和反序列化器。通过以下语句来实现:

call.registerTypeMapping(Book.class,

?????? ????????????????????? new org.apache.axis.encoding.ser.BeanSerializerFactory(Book.class,???????

?????? ????????????????????? new org.apache.axis.encoding.ser.BeanDeserializerFactory(Book.class,qn));

?

?

最后在 build.xml 中增加对 deploy.wsdd 文件的部署。内容如下:

?

?

<target name="deployws" depends="compile">

????????????? <axis-admin url="http://localhost:8080/myservices/servlet/AxisServlet"

?????????????????????????????????? xmlfile="${src.dir}/chen/axisguide/ch4/deploy.wsdd"/>

?????????????

</target>

?

?

5?????? 处理器 (Handler)

Axis 引擎在处理消息过程中,可以自定义处理器对请求或响应的消息进行拦截处理,处理器的动作对服务的实 现部分透明。这种机制可以将日志、安全检查、加密解密等与业务无关的操作抽取出来单独处理,降低模块间的依赖关系。

?

自定义处理器时从 org.apache.axis.handlers.BasicHandler 继承,在方法 invoke(MessageContext msgContext) 进行拦截处理。消息等运行环境信息可以从 msgContext 得到。

?

自定义处理器要发挥作用,需要在 wsdd 文件中进行说明,方法如下:

1- ??? <handler name=”handlername” type=”java:classname”> 定义处理器,如果要给处理器传递参数,可在 <handler> 下用 <parameter name=”name” value=”value” /> 进行说明。 之后在自定义处理器类代码中用 getOption(“name”) 可得到 value 的值。

2- ??? <service> 中 用 <requestFlow> <responseFlow> 定义在请求消息流或返回消息流中要调用的处理器。如果有多个处理器,则按其在 <requestFlow> <responseFlow> 中排列顺序依次调用。格式如下:

<service>

?????? <requestFlow>

????????????? <handler type=”handlername” />

?????? </requestFlow>

</service>

?

?

下面的例子中服务器端和客户端代码使用第 3 节的代码,在请求消息流中增加两个处理器,第一个处理器在控制台打印出 SOAP 包的 body 内容,然后在 MessageContext 中设置一个属性值;第二个处理器从 MessageContext 中取出第一个处理器设置的属性值,在控制台打印出来。

?

第一个处理器原代码如下:

FirstHandler.java

package chen.axisguide.ch5;

?

import javax.xml.soap.SOAPException;

?

import org.apache.axis.AxisFault;

import org.apache.axis.Message;

import org.apache.axis.MessageContext;

import org.apache.axis.handlers.BasicHandler;

import org.apache.axis.message.SOAPBody;

?

public class FirstHandler extends BasicHandler {

?

?????? public void invoke(MessageContext msgContext) throws AxisFault {

?????????????

????????????? Message reqMsg = msgContext.getRequestMessage();

?????????????

????????????? try {

???????????????????? SOAPBody reqBody = (SOAPBody) reqMsg.getSOAPBody();

???????????????????? System.out.println("===================================");

???????????????????? System.out.println("request SOAP body " + reqBody.getAsString());

???????????????????? System.out.println("===================================");

???????????????????? // 设置属性传递到下一个 handler

???????????????????? msgContext.setProperty("handler1","handler1 processed");

????????????????????

????????????? } catch (SOAPException e) {

????????????????????

???????????????????? e.printStackTrace();

????????????? } catch (Exception e) {

????????????????????

???????????????????? e.printStackTrace();

????????????? }

?????????????

?????? }

?

}

?

?

?

第二个处理器原代码:

SecondHandler.java

?

package chen.axisguide.ch5;

?

import org.apache.axis.AxisFault;

import org.apache.axis.MessageContext;

import org.apache.axis.handlers.BasicHandler;

?

public class SecondHandler extends BasicHandler {

?

?????? public void invoke(MessageContext msgContext) throws AxisFault {

?????????????

????????????? System.out.println("Get data from previous handler : " + msgContext.getProperty("handler1"));

?

?????? }

?

}

?

?

?

wsdd 文件内容如下:

deploy.wsdd

?

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

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

?? ? <handler name="handler1" type="java:chen.axisguide.ch5.FirstHandler" />

??? <handler name="handler2" type="java:chen.axisguide.ch5.SecondHandler" />

??????????

??? <service name="EchoService" provider="java:RPC" >

?????? <parameter name="className" value="chen.axisguide.ch5.EchoService" />

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

?????? <requestFlow>

?????????? <handler type="handler1" />

?????????? <handler type="handler2" />

?????? </requestFlow>

??? </service>

???

</deployment>

?

?

build.xml 中增加对 deploy.wsdd 文件的部署处理。内容如下:

?

<target name="deployws" depends="compile">

????????????? <axis-admin url="http://localhost:8080/myservices/servlet/AxisServlet"

???????????????????????????????????????????????? xmlfile="${src.dir}/chen/axisguide/ch5/deploy.wsdd"/>

</target>

?

?

服务端和客户端原代码和第 3 节相同,不再列出。

Eclipse 中用 Ant 运行 build.xml ,在 Tomcat 中重新载入 Web 应 用,然后在 Eclipse 中运行 Client.java ,在 Tomcat 的控制台将会打印出 SOAP body 信息以及 handler1 属性值。


?

6?????? 访问控制

开发好 WebService 并向外暴露服务后,由于 WebService 访问协议都是公开的,客户端只要知道服务的 wsdl ,就可以访问 WebService 中的方法。为防止非法的访问,可以要求客户端访问 WebService 时提供用户名和口令,只有在服务端通过身份认证后才可继续访问方法,否则请求被拒绝。

下面看一下 Axis 中 如何使用用户名、口令来控制对 WebService 的访问。

myservices/WEB-INF 下创建一个名为 users.lst 的文本文件,一行表示一对用户名、口令,之间用空格分隔,内容如下:

user1 password1

user2 password2

?

实现一个 WebService ,它有一个 foo() 方 法,该方法打印出通过身份认证的用户的用户名,代码如下:

SecurityService.java

?

package chen.axisguide.ch6;

?

import org.apache.axis.MessageContext;

?

public class SecurityService {

?????? public void foo() {

?????????????

????????????? MessageContext msgContext = MessageContext.getCurrentContext();

????????????? System.out.println(" 你 已通过身份认证 !");

????????????? System.out.println(" 你 的用户名 : " + msgContext.getUsername());

?????????????

?????? }

}

?

?

为了让 Axis 知晓要对该服务的访问验证用户名和口令,需要在 wsdd 文件中增加一个 Axis 自带的处理器 SimpleAuthenticationHandler ,该处理器会从 MessageContext 中取出用户名和口令,并与 users.lst 中的用户名和口令进行比对,如果匹配,则通过验证,继续后面的处理,否则抛出 (401)Unauthorized 异常。

deploy.wsdd

?

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

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

???????????

??? <service name="SecurityService" provider="java:RPC" >

?????? <parameter name="className" value="chen.axisguide.ch6.SecurityService" />

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

?????? <requestFlow>

?? ??????? <handler type="java:org.apache.axis.handlers.SimpleAuthenticationHandler" />

? ???? </requestFlow>

? ?? </service>

</deployment>

?

?

?

客户端在访问 WebService 时,需要在 Call 对 象中设置在 users.lst 文件中已有的用户名和对应的口令。客户端代码如下:

?

?

package chen.axisguide.ch6;

?

import java.rmi.RemoteException;

?

import javax.xml.rpc.ServiceException;

?

import org.apache.axis.AxisFault;

import org.apache.axis.client.Call;

import org.apache.axis.client.Service;

?

?

/**

? * 访问 SecurityService 的客户端

? *

? *

? */

public class Client {

?

?????? /**

?????? ? * @param args

?????? ? * @throws ServiceException

?????? ? * @throws RemoteException

?????? ? */

?????? public static void main(String[] args) throws ServiceException,RemoteException {

????????????? // wsdl address 节点的 location 属性

????????????? String endpoint = "http://localhost:8080/myservices/services/SecurityService";

????????????? // 要调用的方法名

????????????? String method = "foo";

?????????????

????????????? Service service = new Service();

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

????????????? // 设置客户端访问的远程端点

????????????? call.setTargetEndpointAddress(endpoint);

????????????? // 设置用户名和口令

????????????? call.setUsername("user1");

????????????? call.setPassword("password1");

??????

?????????????

????????????? // 调用远程方法

????????????? try{

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

????????????? }catch(AxisFault e) {

???????????????????? System.err.println(e.getFaultString());

????????????? }

?????? }

?

}

Call 对象用 setUserName() setPassword() 来设置用户名和口令。

Axis 自带的身份认证功能比较简单,如果其安全性不能满足应用系统的要求,可以自定义一个处理器替代 SimpleAuthenticationHandler ,在自定义处理器中采用其他的安全框架(如 Acegi http://www.acegisecurity.org/ )来保护你的 WebService

?

7?????? 总结

从上面的实例可以看出, Axis 在 开发 WebService 方面具有如下优势:

l ???????? 轻量级: Axis 本身只需要 Servlet 容器就可运行,因此能够在大多数轻量级的 Web 应 用服务器上运行;另外在 Axis 中服务的实现类只要求是一个 POJO , 没有强制要求实现特定接口或从特定父类继承,这使得开发和测试非常容易,不需要为提高开发效率而购置重量级的 IDE

?

l ???????? 扩展性好:在 Axis 中, 可以通过加入自定义处理器( Handler )方式来扩展 Axis 的 功能,并且这种功能的增加对业务部分可以做到透明,即业务代码中不需要为使用增加的功能而修改代码。

?

l ???????? 可移植性强: Axis 可 以在支持 Servlet 的容器中运行,运行于其中的 WebService 也就可以在现有的大多数的 Web 应用服务器上运行,不需要对服务的实现代码做任何的改动。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读