j2ee web service开发(六) 跟其它编程语言写的Web服务通信 Holder类型
要弄清楚什么是 Holder 类型,得先搞清楚 IN 参数, OUT 参数, INOUT 参数的概念。
IN 参数是 JAVA 因有的参数, OUT , INOUT 参数不是 JAVA 固有的。
复制传递:IN参数
java 编程语言对作为参数传递给方法调用的所有原始值采用复制传递的方式,即传递的值是方法调用中所使用变量的复制,而不是原始值本身。比如定义一个方法
test(int intValue,Date dateValue){
intValue=5;
dateValue=new Date(0);
}
在作如下调用时
int intValue=1;
Date dateValue=new Date();
test(intVlaue,dateValue);
System.out.println(intValue) // 打印1
System.out.pritnln(dateValue) // 打印现在的时间。
但是在 test 方法中对参数的值作了修改。而实际的参数值并未发生改变。
引用传递 : INOUT 参数 OUT 参数 .
在实现引用传递的编程语言中,如果 test 方法的两面个参数定义为引用传递 , 对上述 test 方法调用后,再打印 intValue 跟 dateValue 的值,会发现这两个值已经发生了改变。但是 OUT 参数更象一个返回值,因为值要从方法中传出而不是传入。使用 OUT 参数数,激活方法前不访问变量的值,即传入的值被忽略了。
H older 类:
在 JAX-RPC 中支持 INOUT,OUT 参数。 Holder 是一个接口,它只是提供了一个补救措施,以在 java 中支持引用传递。这样就使得需要用 java 与支持 INOUT,OUT 参数的编程语言写的 web 服务进行通信 .
从 WSDL 映射 HOLDER 类型 :
接口定义
public interface HolderTestBeanInterface1 extends Remote {
public void echoCalendar(CalendarHolder val, Date date) throws
RemoteException;
public void echoBeanHolder(BeanTestHolder beanTestHolder,BeanTest beanTest) throws
RemoteException;
}
WSDL 文档
<?xml version="1.0" encoding="UTF-8"?>
<definitions name='HolderTestBeanInterface1' targetNamespace='http://holder' xmlns='http://schemas.xmlsoap.org/wsdl/' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='http://holder' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
<message name='HolderTestBeanInterface1_echoCalendar'>
<part name='Calendar_1' type='xsd:dateTime'/><! — 不要这一行 , 它就是一个 OUT 参数 - à
<part name='Date_2' type='xsd:dateTime'/>
</message>
<message name='HolderTestBeanInterface1_echoCalendarResponse'>
<part name='Calendar_1' type='xsd:dateTime'/>
</message> <portType name='HolderTestBeanInterface1'>
<operation name='echoCalendar' parameterOrder='Calendar_1 Date_2'>
<input message='tns:HolderTestBeanInterface1_echoCalendar'/>
<output message='tns:HolderTestBeanInterface1_echoCalendarResponse'/>
</operation>
</portType>
…
标记为 Calendar_1 的 part 元素既在 input 消息中又在 ouput 消息中 ,jax-rpc 编译器知道它是一个 INOUT 类型 , 同时也需要 Holer 类型。如果在output消息定义一个part元素,这表示它是一个返回值或者一个OUT参数,如果part是一个OUT参数,part标记会列在operation元素的parameterOrder属性中.OUT参数也需要Holder类型.
Javax.xml.rpc.holders包中提供了一个Holder类,用于映射到java原始类型的INOUT参数和OUT参数。如IntHolder等,同时也提供了一组为nillable内置类型定义的Holder类型,如IntegerWrapperHolder等.
自定义Holder类型。必须实现Holder标志接口, 其属性变量名必须为 value 并且必须定义一个空的构造函数就象下面这样:
public class BeanTestHolder implements javax.xml.rpc.holders.Holder {
public BeanTest value;
public BeanTestHolder(){
}
public BeanTestHolder(BeanTest beanTest){
value=beanTest;
}
}
Jboss Web Service 的 Holder 类型的具体实现 , 采用 Jboss 4.04 版本 .
定义一个 bean 类 :
public class BeanTest {
private String beanName;
public BeanTest(){
}
public String getBeanName() {
return beanName;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}
给 bean 定制一个 Holder:
package holder;
public class BeanTestHolder implements javax.xml.rpc.holders.Holder {
public BeanTest value;
public BeanTestHolder(){
}
public BeanTestHolder(BeanTest beanTest){
value=beanTest;
}
}
定义一个接口 :
public interface HolderTestBeanInterface1 extends Remote {
public void echoCalendar(CalendarHolder val, Date date) throws
RemoteException;
public void echoBeanHolder(BeanTestHolder beanTestHolder,BeanTest beanTest) throws
RemoteException;
}
接口的实现类 :
import javax.xml.rpc.holders.*;
import java.util.Date;
public class HolderTestBean implements HolderTestBeanInterface1 {
public void echoCalendar(CalendarHolder val,Date date) {
System.out.println("echoCalendar: " + val.value.getTime());
val.value.setTime(new Date());
System.out.println(date);
}
public void echoBeanHolder(BeanTestHolder beanTestHolder,BeanTest beanTest){
BeanTest beantest=beanTestHolder.value;
System.out.println(beantest.getBeanName()+ " holder ");
beantest.setBeanName(" new name ");
System.out.println(beantest.getBeanName()+ " holder ");
System.out.println(beanTest.getBeanName()+ " bean ");
beanTest.setBeanName(" new name too ");
System.out.println(beanTest.getBeanName()+" bean ");
}
}
用于 jboss 自带的 wstools 工具的配置文件 wstools-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--
wstools -cp classes -config wstools-config.xml
-->
<configuration xmlns="http://www.jboss.org/jbossws-tools"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.org/jbossws-tools http://www.jboss.org/jbossws-tools/schema/jbossws-tool_1_0.xsd">
<java-wsdl>
<service name="HolderTestBeanInterface1" style="rpc" endpoint="holder.HolderTestBeanInterface1"/>
<namespaces target-namespace="http://holder" type-namespace="http://holder"/>
<mapping file="HolderTestBeanInterface1.xml"/>
<webservices servlet-link="HolderTestBeanInterface1"/>
</java-wsdl>
</configuration>
生成所需的 webservices.xml,jax-rpc 映射文件 , 及 wsdl 文档
wstools -config wstools-config.xml
把生成的 wsdl 文件夹 ,webservices.xml 及映射文件放到 web-inf 目录下。
配置 web.xml 文件
<servlet>
<display-name>HolderTestBeanInterface1 Servlet</display-name>
<servlet-name>HolderTestBeanInterface1</servlet-name>
<servlet-class>holder.HolderTestBean</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HolderTestBeanInterface1</servlet-name>
<url-pattern>/HolderTestBeanInterface1</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>HolderTestBeanInterface1</servlet-name>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
打包成 war 文件并发布
客户端的调用 :
import java.net.URL;
import javax.xml.rpc.*;
import javax.xml.namespace.QName;
import java.util.*;
import java.io.File;
import javax.xml.rpc.holders.CalendarHolder;
import org.jboss.ws.jaxrpc.ServiceFactoryImpl;
public class ClientTest {
private HolderTestBeanInterface1 getPort() throws Exception {
ServiceFactoryImpl factory = new ServiceFactoryImpl();
URL wsdlURL = new File(
"holderTest/WEB-INF/wsdl/HolderTestBeanInterface1.wsdl").toURL();
URL mappingURL = new File(
"holderTest/WEB-INF/HolderTestBeanInterface1.xml").toURL();
QName qname = new QName("http://holder", "HolderTestBeanInterface1");
Service service = factory.createService(wsdlURL, qname, mappingURL);
HolderTestBeanInterface1 port = (HolderTestBeanInterface1) service.getPort(HolderTestBeanInterface1.class);
return port;
}
public static void main(String[] args) throws Exception{
ClientTest clienttest = new ClientTest();
HolderTestBeanInterface1 h=clienttest.getPort();
Date date=new Date();
System.out.println(date+ " date begin... ");
GregorianCalendar value = new GregorianCalendar(2006, 1, 1, 23, 59, 59);
CalendarHolder holder = new CalendarHolder(value);
System.out.println(holder.value.getTime()+" calendarHolder begin... ");
h.echoCalendar(holder,date);
System.out.println(holder.value.getTime()+" calendarHolder end ... ");
System.out.println(date+ " date end ... ");
BeanTest beanTest=new BeanTest();
beanTest.setBeanName("test");
BeanTest beanTest2=new BeanTest();
beanTest2.setBeanName("test2");
System.out.println(beanTest.getBeanName()+" holder begin.. ");
System.out.println(beanTest2.getBeanName()+" bean begin..");
BeanTestHolder beanTestHolder = new BeanTestHolder(beanTest);
h.echoBeanHolder(beanTestHolder,beanTest2);
System.out.println(beanTest2.getBeanName() + " bean end..");
System.out.println(beanTestHolder.value.getBeanName()+" holder end.. ");
}
}
如何调用 web 服务参见手记 j2ee web serivce 开发 ( 一 )
对比一下调用前后的输出就能明白 Holder 类型的作用了 .
完整的示例下载
欢迎加入QQ群