本文主要介绍使用service方式实现Web服务、复杂类型参数或者返回值以及面向消息/文档的服务类型,同时还会简单提及Web服务的会话管理以及安全问题等等。
前段时间我的一篇文章《应用AXIS开始Web服务之旅》介绍了如何通过AXIS这个项目来实现Web服务的功能。该文章主要介绍AXIS的结构、如何使用 jws文件的方式开发一个简单的Web服务,并用了比较大的篇幅来介绍Web服务的客户端编程,应该说是使用AXIS开发Web服务的入门篇,本文假设你已经看过《应用AXIS开始Web服务之旅》并对AXIS有一定的基础,在这个基础上我们将要介绍的内容有几个方面包括使用service方式实现Web 服务、复杂类型参数或者返回值以及面向消息/文档的服务类型,同时还会简单提及Web服务的会话管理以及安全问题等等。
在开始我们的文章之前,我们还需要搭建一个环境,我们需要一个支持Web服务的web应用程序并假设名字为axis,如何建立请参照《应用AXIS开始Web服务之旅》文章中的介绍。
使用定制发布编写Web服务
使用jws文件的方式编写Web服务具有方便、快捷的优点,它可以很快的将你已有的类发布成Web服务。但是更多的时候这并不是一个好的主意,因为这种做法引发的问题是我们必须要将已有类的源码发布出来,因为更多的时候我们并不想这样做;另外虽然你可以先用工具开发并调试完毕一个java文件后再改名为 jws,但是这多少有些便扭,而且并不是类中的所有方法你都想发布成可通过Web服务来访问的,这时候你就必须将这些方法的修饰符改为不是public 的,这就跟你原有的类不同步,以后的修改将会更加的麻烦。
在这里我把定制发布方式称为service方式,就好像JSP的出现不会使Servlet失宠的道理一样,有了jws,service方式还是有它的用武之地,而且是大放异彩。发布一个service方式的 Web服务需要两部分内容:类文件以及Web服务发布描述文件。下面我们使用一个简单的例子来讲述这个过程。
首先我们需要一个service类,这个类跟普通的类没有任何区别,下面是我们实现一个城市便民服务的类,我们需要将CityService类的两个方法 getZip和getTel发布成Web服务,编译该文件并把class文件拷贝到<webapp>/WEB-INF/classes对应目录下。
Package lius.axis.demo;
/**
* 该类实现了城市服务,用于发布成Web服务
* @author Liudong
*/
public class CityService {
/**
* 获取指定城市的邮编
* @param city
* @return
*/
public String getZip(String city) {
return "510630";
}
/**
* 获取指定城市的长途区号
* @param city
* @return
*/
public String getTel(String city) {
return "020";
}
}
程序已经完成,下面是发布这个Web服务。打开<webapp>/WEB-INF/server-config.wsdd如果这个文件不存在则创建一个新的文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<globalConfiguration>
<parameter name="adminPassword" value="admin"/>
<parameter name="attachments.implementation"
value="org.apache.axis.attachments.AttachmentsImpl"/>
<parameter name="sendXsiTypes" value="true"/>
<parameter name="sendMultiRefs" value="true"/>
<parameter name="sendXMLDeclaration" value="true"/>
<parameter name="axis.sendMinimizedElements" value="true"/>
<requestFlow>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="session"/>
</handler>
<handler type="java:org.apache.axis.handlers.JWSHandler">
<parameter name="scope" value="request"/>
<parameter name="extension" value=".jwr"/>
</handler>
</requestFlow>
</globalConfiguration>
<handler name="LocalResponder" type="java:org.apache.axis.transport.local.LocalResponder"/>
<handler name="URLMapper" type="java:org.apache.axis.handlers.http.URLMapper"/>
<handler name="Authenticate" type="java:org.apache.axis.handlers.SimpleAuthenticationHandler"/>
<service name="city" provider="java:RPC">
<!-- 服务类名 -->
<parameter name="className" value="lius.axis.demo.CityService"/>
<!-- 允许访问所有方法 -->
<parameter name="allowedMethods" value="*"/>
</service>
<transport name="http">
<requestFlow>
<handler type="URLMapper"/>
<handler type="java:org.apache.axis.handlers.http.HTTPAuthHandler"/>
</requestFlow>
</transport>
<transport name="local">
<responseFlow>
<handler type="LocalResponder"/>
</responseFlow>
</transport>
</deployment>
其中粗斜体的部分是我们服务的配置信息,启动Tomcat并打开浏览求访问地址: http://localhost:8080/axis/services/city?wsdl ,下面是浏览器显示我们Web服务的WDSL数据。
当然了,这个过程比起jws方式来说是稍微麻烦一点,你可以把它想象成你发布一个servlet一样,创建servlet类然后在web.xml中加入配置信息。
处理复杂类型参数和返回值
之前我们做的演示程序都很简单,方法的参数和返回值都是简单类型的数据,但是在实际应用过程中往往没有这么简单。在使用面向对象的编程语言时,我们会希望数据类型可以是某个对象,比如我们提供一个接口用来发送短信息,那么我们希望接口的参数是一个消息对象,这个消息对象封装了一条信息的所有内容包括发送者、接收者、发送时间、优先级、信息内容等等,如果我们把每个内容都做成一个参数,那这个接口的参数可能会非常的多。因此封装成对象是很有必要的。
在使用Axis来编写Web服务时对复杂类型数据的处理同样也是非常简单。Axis要求复杂类型对象的编写必须符合JavaBean的规范,简单的说就是对象的属性是通过getter/setter方法来访问的。来看看下面这个简单的例子所输出的WSDL信息有何特殊的地方。为了简便,我们还是使用jws来编写,需要编写三个文件:sms.jws,Message.java,Response.java。
//文件名:sms.jws
import lius.axis.demo.*;
public class sms{
/**
* 短信息发送Web服务接口
*/
public Response send(Message msg) throws Exception{
System.out.println("CONTENT:"+msg.getContent());
Response res = new Response();
res.setMessage(msg);
res.setCode(0);
res.setErrorText("");
return res;
}
}
//Message.javapackage lius.axis.demo;
/**
* 欲发送的信息
* @author Liudong
*/
public class Message {
private String from;
private String to;
private String content;
private int priority;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public int getPriority() {
return priority;
}
public void setPriority(int priority) {
this.priority = priority;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
}
//Response.javapackage lius.axis.demo;
/**
* 信息发送回应,在这里我们做了一个对Message 类的引用
* @author Liudong
*/
public class Response {
private int code;
//发送结果代码
private String errorText;
private Message message;
//发送的原始信息
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getErrorText() {
return errorText;
}
public void setErrorText(String errorText) {
this.errorText = errorText;
}
public Message getMessage() {
return message;
}
public void setMessage(Message message) {
this.message = message;
}
}
编译Message.java和 Response.java并将编译后的类文件拷贝到axis/WEB-INF/classes对应包的目录下,sms.jws拷贝到axis目录,访问 http://localhost:8080/axis/sms.jws?wsdl即可看到WSDL信息,这些信息与之前不同的在于下面列出的内容(注意粗斜体部分内容):
<wsdl:types>
<schema targetNamespace="http://demo.axis.lius" xmlns="http://www.w3.org/2001/XMLSchema">
<import namespace="http://schemas.xmlsoap.org/soap/encoding/" />
<complexType name="Message">
<sequence>
<element name="content" nillable="true" type="xsd:string" />
<element name="from" nillable="true" type="xsd:string" />
<element name="priority" type="xsd:int" />
<element name="to" nillable="true" type="xsd:string" />
</sequence>
</complexType>
<complexType name="Response">
<sequence>
<element name="code" type="xsd:int" />
<element name="errorText" nillable="true" type="xsd:string" />
<element name="message" nillable="true" type="tns1:Message" />
</sequence>
</complexType>
</schema>
</wsdl:types>
这里定义了两个类型Message和 Response,就是我们接口的参数类型以及返回值的类型。现在再使用WSDL2Java工具来生成客户端Helper类看看Axis帮我们做了什么?它会自动帮我们生成两个类Message和Response,包名与类名都跟我们刚才定义的一致,你可以打开看看跟我们刚才编写的类差别多大?这两个类添加了很多方法例如getTypeDesc、getSerializer、getDeserializer等等。现在你就可以随便写个小程序测试一下了,我们就不在累赘了。Service方式Web服务的处理跟jws是类似的,不同在于service方式需要在server-config.wsdd添加类型的映射配置,下面给出一个配置的示例,读者可以根据实际情况进行修改。
<service name="SmsService" provider="java:RPC">
<parameter name="className" value="lius.axis.demo.SmsService"/>
<parameter name="allowedMethods" value="send"/>
<operation name="send" returnType="ns:Response">
<parameter name="msg" type="ns:Message"/>
</operation>
<!-- 这里定义了方法的参数以及返回值 -->
<typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
qname="ns:Message"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
type="java:lius.axis.demo.Message" xmlns:ns="SmsService"/>
<typeMapping
deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
qname="ns:Response"
serializer="org.apache.axis.encoding.ser.BeanSerializerFactory"
type="java:lius.axis.demo.Response" xmlns:ns="SmsService"/>
</service>
其他编程语言也都可以借助语言本身所附带的工具来生成这些复杂类型,如果你嫌麻烦的话可以使用XML来描述这些复杂类型,这样就简单很多。
面向消息/文档的Web服务类型
我们前面介绍的服务方式是基于RPC(远程过程调用)方式,这也是Web服务最常用的方式。面向消息/文档的的类型跟RPC不同的是它提供了一个更底层的抽象,要求更多的编程工作。客户端可以传入任何的XML文档,得到的响应不一定是SOAPEnvelope,可以返回任何它所需要的东西,甚至不返回。虽然这对开发者来说非常的灵活,但是这种通讯类型在实际的应用中并不常见。面向消息/文档的Web服务主要适合于下面几种情况,比如批量处理,基于表单的数据导入,有需要返回非XML数据时,Web服务器实现中要求直接访问传输层等等。
对于RPC类型的服务需要在全局配置文件server-config.wsdd中设置一行<service ... provider="java:RPC">,其中RPC就是服务的方式,而对于面向消息/文档的服务类型那java:RPC就要替换成为 Message,并且面向消息/文档的服务类型必须通过WSDD配置来发表。对于完成面向消息服务的类,其方法必须具有以下的格式:
public Element[] methodName(Element [] elems)
其中methodName为你自定义的方法名。在Axis的目录下可以找到MessageService.java,这就是一个完成了该类型的服务类,该服务的在WSDD中的配置如下:
<deployment name="test" xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">
<service name="MessageService" style="message">
<parameter name="className" value="samples.message.MessageService"/>
<parameter name="allowedMethods" value="methodName"/>
</service>
</deployment>
不管是什么内容的Web服务,对客户端来说都是一样的,使用WSDL2Java来生成的客户端Helper类的MessageService接口如下:
/**
* MessageService.java
*
* This file was auto-generated from WSDL
* by the Apache Axis WSDL2Java emitter.
*/
package liudong.axis.services.MessageService;
public interface MessageService extends java.rmi.Remote {
public java.lang.Object echoElements(java.lang.Object part) throws java.rmi.RemoteException;
}
我从哪里可以获得…
Axis 文档中有一句话很有意思,对于绝大多数类似于"我从哪里可以获得…"的问题,答案都在MessageContext类中。通过 MessageContext类你可以获取下面几个内容,一个AxisEngine实例的引用;请求以及回应的信息;验证信息以及对于Servlet规范中的实例引用等等。例如当我们需要客户端的IP地址时我们可以通过下面代码片段获取:
/**
* 获取客户端请求
* @return
*/
private HttpServletRequest getRequest() throws Exception{
MessageContext context = MessageContext.getCurrentContext();
HttpServletRequest req = (HttpServletRequest)context.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
return req.getRemoteHost();
}
在类HTTPConstants中,所有以MC_开头的常量就是你所可以获取到的信息,例如上面通过MC_HTTP_SERVLETREQUEST获取对应Servlet规范中的HTTP请求。更详细的信息可以通过查询API文档获取。
Web服务会话管理
在Web 服务中我们可以借助HTTP以及HTTP Cookie来处理会话信息。前面我们介绍了大多数对Axis的管理都是通过MessageContext实例来完成的。下面的例子首先验证用户的登录帐号与口令如果正确则在会话中保存用户的登录信息,并提供接口供客户端获取密码。
import org.apache.axis.MessageContext;
import org.apache.axis.session.Session;
public class login{
public boolean login(String user, String pass){
MessageContext mc = MessageContext.getCurrentContext();
Session session = mc.getSession();
session.set("user",user);
//保存用户名与口令
session.set("pass",pass);
return true;
}
public String getPassword(String user){
MessageContext mc = MessageContext.getCurrentContext();
Session session = mc.getSession();
if(user.equals(session.get("user")))
return (String)session.get("pass");
return null;
}
}
对于服务器端来讲只需要通过MessageContext实例获取Session对象即可进行会话级的数据保存或者读取,而对于通过Axis的WSDL2Java工具生成的客户端来讲还需要做一个特殊的设置,请看下面客户端代码片段。
public static void main(String[] args) throws Exception {
LoginServiceLocator lsl = new LoginServiceLocator();
lsl.setMaintainSession(true);
Login login = lsl.getlogin();
if(login.login("ld","haha"))
System.out.println("PWD:"+login.getPassword("ld"));
else
System.out.println("Login failed.");
}
代码中的粗体部分就是让Axis帮助我们自动处理服务器返回的Cookie信息以保证会话正常工作。
保护Web服务
网络的安全问题永远是需要最先考虑的问题,可是怎么能让我们的Web服务更加安全呢?为此Axis建议可以根据实际的需要采取以下的几种方法。
1. 使用HTTPS传输方式 该方式需要在Web服务器上进行配置同时需要客户端的支持。该措施有效的防止数据在网络传输过程中被窥视。
2. 重命名Axis已有的一些名字,例如AdminService、AxisServlet,删除Axis目录下一些无用的程序,例如happyaxis.jsp以及一些无用的jar包等。
3. 通过设置axis.enableListQuery的值为false来停止AxisServlet列出所有服务的功能。
4. 禁止自动生成WSDL的功能
5. 使用过滤器来增加一些验证功能,例如客户端的地址等。
最常用的不外乎上面几个,至于更详细的资料可以参考Axis解压目录下的docs/reference.html文件的详细介绍。
参考资料
* 《应用AXIS开始Web服务之旅》 http://www.ibm.com/developerworks/cn/webservices/ws-startaxis/index.html
* IBM开发者站点Web服务专区 http://www.ibm.com/developerworks/cn/webservices
* Apache网站AXIS项目 http://ws.apache.org/axis/
* W3C之Web服务 http://www.w3.org/2002/ws/
关于作者
刘冬,一直使用J2EE从事移动业务方面的开发。现在可以通过Java自由人网站来跟我联系,网址是: http://www.javayou.com;另外我的邮件地址是 winter.lau@163.com。
分享到:
相关推荐
项目收集的axis的相关资料~~ ...AXIS实现Web服务深入篇.TXT AXIS学习笔记.txt WebService之axis的复杂对象传输方案.txt 使用Apache Axis部署 Web服务时的常见问题及其解决方法.txt 使用Axis开发Web Service程序.txt
本篇文章将深入探讨如何使用Axis实现Web服务,包括服务端和客户端的设置,以及相关jar包的使用。 首先,让我们了解Web服务的基本概念。Web服务是通过SOAP(简单对象访问协议)和WSDL(Web服务描述语言)进行通信的...
这篇博客文章将引导我们如何利用Apache Axis来生成Web服务客户端,从而实现天气预报功能的开发。下面,我们将深入探讨这个过程中的关键知识点。 首先,我们需要理解什么是Web服务。Web服务基于开放标准,如SOAP...
本篇文章将深入讲解如何使用Apache Axis1.4实现Web服务。 首先,我们需要理解Axis1.4的特点。作为较早版本的Axis,它已经经过了长期的测试和优化,具有良好的稳定性和兼容性。开发者可以依赖它来构建可靠的Web服务...
本篇文章将深入探讨如何手写Axis实现Web服务的通讯,这是一项对于开发者来说非常实用的技能,特别是对于需要跨系统交互或者构建分布式应用的场景。 首先,我们需要了解什么是Axis。Axis是Apache软件基金会开发的一...
标题“用Axis开发基于Java的Web服务”指向的是一个关于使用Apache Axis...它会深入讲解如何利用Java和Axis构建可扩展、可互操作的Web服务,并且可能包括实际操作的示例和源代码,帮助读者更好地理解和应用这些概念。
这篇博客文章可能详细介绍了如何使用Axis来部署和运行Web服务。 在描述中提到的“NULL”,可能意味着博客作者没有提供具体的描述信息,或者该字段在原始数据中是空的。因此,我们主要依据标题和标签来推测内容。 ...
本篇文章将深入探讨如何使用Java和Axis2来实现一个完整的Web服务。 首先,让我们理解什么是Web服务。Web服务是一种基于网络的软件应用,它通过标准的协议(如HTTP)提供数据交换和业务逻辑调用。SOAP(Simple ...
这篇学习笔记将深入探讨如何使用Axis来开发Web服务。 1. **Web服务基础** Web服务是通过SOAP(Simple Object Access Protocol)消息交换,使用WSDL(Web Services Description Language)来定义服务接口,以及利用...
本篇文章将深入讲解使用Apache Axis开发Web服务的简单步骤,帮助你实现不同项目间的通信。 首先,理解Web服务的基本概念至关重要。Web服务是通过SOAP(Simple Object Access Protocol)消息在HTTP协议上进行通信的...
本篇文章将深入探讨如何使用Axis1来创建并运行一个基本的"Hello, World!"示例,帮助初学者理解Web服务的工作原理。 首先,了解SOAP是理解Axis1工作原理的关键。SOAP是一种轻量级的协议,用于在Web上交换结构化的、...
通过本篇指南,我们不仅掌握了在MyEclipse环境下使用Apache Axis构建Web Service的基本步骤,还深入了解了WSDL的设计与代码自动生成的流程。此外,了解了如何利用MyEclipse集成的工具链提高开发效率,以及如何进行...
本篇文章将深入探讨如何使用Axis2来实现文件的上传和删除功能,这对于构建分布式系统和跨平台应用至关重要。 首先,我们需要了解Axis2的基本概念。Axis2 是一个Web服务引擎,它支持SOAP 1.1和1.2以及RESTful风格的...
总的来说,这篇博客应该深入浅出地介绍了Axis2服务发布和客户端调用的整个过程,对于学习和理解Web服务的开发和交互非常有帮助。如果你是初学者,跟随这个示例可以快速上手;如果你是开发者,它可能为你提供了解决...
Apache Axis是实现Web服务的重要工具,尤其在Java环境中,它为开发、部署和消费Web服务提供了全面的支持。本篇文章将深入探讨如何利用Apache Axis来创建Web服务。 一、Web服务基础 Web服务基于开放标准,如XML(可...
本篇将深入探讨基于Axis2的Web服务,包括其概念、优势以及如何创建和使用。 1. **Axis2简介** Axis2是Apache Axis的第二代版本,它提供了一个轻量级、高性能的Web服务引擎。Axis2支持多种编程模型,如SOAP消息处理...
解压并研究这些文件可以帮助更好地理解和实践文件上传下载的Axis实现。 总结,Axis框架为文件的上传和下载提供了便利的实现方式,通过SOAP协议和Java的IO流处理,可以在Web服务之间安全有效地传输文件。熟悉和掌握...
本篇文章将深入探讨如何利用Axis和wsdd(Web Services Deployment Descriptor)文件来部署Web服务。 首先,让我们了解什么是wsdd文件。wsdd是Axis用来配置和部署Web服务的XML配置文件,它包含了关于服务端点、消息...
标题 "axis的一些总结" 暗示了这篇内容主要聚焦于Axis在IT领域的应用,特别是与Web服务相关的技术。Axis是一个开源的Java Web服务框架,它允许开发人员创建和部署Web服务。这篇总结可能涵盖了Axis的基本概念、安装、...