访问Spring示例JPetStore的OrderService服务

Spring--当前流行的J2EE开发的轻量级框架,提供了对MVC web层、持久化层、声明性事务及远程调用的支持。借助Apache Axis的支持,Spring提供了基于WSDL的WebService服务。

本文主要讨论两个问题,如何提供一个WebService服务以及如何从外部访问该服务。我们研究一下JPetStore示例提供的OrderService。

代码需要以下环境。

1.spring-framework-1.2.8-with-dependencies.zip 解压缩。

2.eclipse3.2+JDK1.5

3.tomcat 5.0

4.数据库mySQL或Oracle9i

至少完成以下准备工作:

1.已经在Tomcat中部署Spring的示例JPetStore

2.可以在本机访问JPetStore的OrderService。

3.在eclipse环境建立jpetstore项目,指定路径(例如c:/spring-framework-1.2.8/samples/jpetstore)

Spring支持多种远程调用机制,本文开头也提到了。这里我们仅讨论基于WSDL的WebService的问题。首先,看如何在Spring中提供一个WebService。很简单,需要2个步骤。

1.编写一个继承ServletEndpointSupport类并实现你要提供的服务的接口。例如JPetStore已经提供了这个类JaxRpcOrderService。

2.编写server-confid.wsdd描述文件,请参照Spring示例查看该文件。以下是其中的一段,用于描述上步骤的服务端点。


注意,上述描述符的beanMapping段落描述了该服务端点的数据类型及其引用或以来类型。后文还会提到这些数据类型的意义。重新启动Tomcat即可。

如何在客户端访问OrderService?这里我们提供一种使用Java在客户端访问该服务的示例以及如何解决遇见错误could not find deserializer for type。通过这个示例,大家会加深对WebSerive工作机制的理解,例如obejct serialization/ deserialization(对象序列化/反序列化)。我们知道,现代的面对对象的语言(例如Java,C#)提供了对象序列化/反序列化机制。对象序列化就是把对象持久化到内存外的存储介质,反序列化就是逆过程。在应用到面向对象的软件系统提供远程调用服务,离不开对象序列化/反序列化机制。WebService基于XML标记语言。一个调用的返回结果如果是一个对象,那么XML文本其实就是对象的存储介质,我们需要反序列化它,把它还原到内存中真实的对象。这个过程Axis已经帮我们完成了。


好了,来看示例代码:


package com.test.www;

import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.rpc.ParameterMode;

import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.springframework.samples.jpetstore.domain.Item;
import org.springframework.samples.jpetstore.domain.LineItem;
import org.springframework.samples.jpetstore.domain.Order;
import org.springframework.samples.jpetstore.domain.Product;
//import org.apache.axis.client.ServiceFactory;
public class TestWebServiceClient {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
String nameSpaceUri = "http://localhost:8090/jpetstore/services/OrderService";
// 创建调用对象
Service service = new Service();
Call call = null;
call = (Call) service.createCall();

QName qn1 = new QName("urn:JPetStore", "Order");
QName qn2 = new QName("urn:JPetStore", "LineItem");
QName qn3 = new QName("urn:JPetStore", "Item");
QName qn4 = new QName("urn:JPetStore", "Product");
call.registerTypeMapping(Order.class, qn1, new BeanSerializerFactory(Order.class, qn1),
new BeanDeserializerFactory(Order.class, qn1));
call.registerTypeMapping(LineItem.class, qn2, new BeanSerializerFactory(LineItem.class, qn2),
new BeanDeserializerFactory(LineItem.class, qn2));
call.registerTypeMapping(Item.class, qn3, new BeanSerializerFactory(Item.class, qn3),
new BeanDeserializerFactory(Item.class, qn3));
call.registerTypeMapping(Product.class, qn4, new BeanSerializerFactory(Product.class, qn4),
new BeanDeserializerFactory(Product.class, qn4));

System.out.println(">>>getOrder");
call.setTargetEndpointAddress(new URL(wsdlUrl));
//调用的服务器端方法
call.setOperationName(new QName("Order", "getOrder"));
//设定传入的参数,这里qn即Order.class
//call.addParameter("arg1", qn1, ParameterMode.IN);
call.addParameter("arg1", qn1, ParameterMode.IN);
//设定返回的参数是Order.class
call.setReturnType(qn1, Order.class);
Order ret = (Order) call.invoke(new Integer[]{1000});
System.out.println("return value is " + ret);
} catch (Exception e) {
e.printStackTrace();
}
}
}


如果遇到过could not find deserializer for type 错误,就会明白了错误表明,在对象反序列化过程中需要的类型无法识别,需要我们注册。

小结

通过以上的例子,我们简单描述了如何提供基于WSDL的WebService以及如何使用Java语言访问该服务。 对象序列化/反序列化是 问题 的关键 。如何在异构环境访问WebService?例如如何在Flex的UI层访问WebService,由于时间原因我们以后再讨论。

你可能感兴趣的:(apache,spring,tomcat,应用服务器,webservice)