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