要弄清楚什么是
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群