這幾天貌似戰(zhàn)斗力無窮,趁著有精力就多更新兩篇。隨著對Axis的研究加深,越感覺webservice是個(gè)很好玩的東西。這篇說一下如何傳遞一個(gè)JavaBean和你自己的一個(gè)special Object。
在第一篇介紹Axis的文章里,我們做了一個(gè)簡單的webservice,我們client side傳遞了String和int類型的數(shù)據(jù)給service object。Service處理之后返回處理結(jié)果給Client。對于大多數(shù)需求,那個(gè)demo顯然已經(jīng)足夠應(yīng)付了。但是如果client端需要傳輸一個(gè)對象給server,那么那個(gè)demo就顯得力不從心了。Axis中提供了遠(yuǎn)程傳輸對象的方法,通過那些方法我們同樣可以隨心的傳遞自己的對象。
我們先從傳遞一個(gè)JavaBean開始,首先編寫一個(gè)JavaBean。
- package com.chnic.bean;
- public class OrderBean {
- private String name;
- private int age;
- private String[] items;
- private int[] price;
- private boolean checked;
- public OrderBean() {
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public boolean isChecked() {
- return checked;
- }
- public void setChecked(boolean checked) {
- this.checked = checked;
- }
- public String[] getItems() {
- return items;
- }
- public void setItems(String[] items) {
- this.items = items;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int[] getPrice() {
- return price;
- }
- public void setPrice(int[] price) {
- this.price = price;
- }
- }
package com.chnic.bean;
public class OrderBean {
private String name;
private int age;
private String[] items;
private int[] price;
private boolean checked;
public OrderBean() {
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public boolean isChecked() {
return checked;
}
public void setChecked(boolean checked) {
this.checked = checked;
}
public String[] getItems() {
return items;
}
public void setItems(String[] items) {
this.items = items;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int[] getPrice() {
return price;
}
public void setPrice(int[] price) {
this.price = price;
}
}
這個(gè)JavaBean的前4個(gè)屬性都很清楚,要解釋一下最后一個(gè)。因?yàn)檫@個(gè)JavaBean被傳遞到Service端處理之后要接著被傳回,用來示例webservce傳進(jìn)和傳出。這個(gè)變量用來區(qū)別傳進(jìn)和傳出的差別。解釋完我們來看下service
- package com.chnic.webservice;
- import com.chnic.bean.OrderBean;
- public class AnalyzeOrder {
- public AnalyzeOrder(){
- }
- public OrderBean process(OrderBean order){
- order.setChecked(true);
- System.out.println("name: " + order.getName() + " age: " + order.getAge());
- for(int i=0; i<order.getItems().length; i++)
- System.out.println("Item " + (i+1) + order.getItems()[i] +
- " and price is " + order.getPrice()[i]);
- return order;
- }
- }
package com.chnic.webservice;
import com.chnic.bean.OrderBean;
public class AnalyzeOrder {
public AnalyzeOrder(){
}
public OrderBean process(OrderBean order){
order.setChecked(true);
System.out.println("name: " + order.getName() + " age: " + order.getAge());
for(int i=0; i<order.getItems().length; i++)
System.out.println("Item " + (i+1) + order.getItems()[i] +
" and price is " + order.getPrice()[i]);
return order;
}
}
Service Object的代碼很簡單,就不解釋了。慣例,我們來編寫發(fā)布文件。
- <deployment xmlns="http://xml.apache.org/axis/wsdd/"
- xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
- <service name="CheckOrder" provider="java:RPC">
- <parameter name="className" value="com.chnic.webservice.AnalyzeOrder"/>
- <parameter name="allowedMethods" value="process"/>
- <beanMapping qname="myNS:Order" xmlns:myNS="urn:AnalyzeOrder"
- languageSpecificType="java:com.chnic.bean.OrderBean"/>
- </service>
- </deployment>
<deployment xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<service name="CheckOrder" provider="java:RPC">
<parameter name="className" value="com.chnic.webservice.AnalyzeOrder"/>
<parameter name="allowedMethods" value="process"/>
<beanMapping qname="myNS:Order" xmlns:myNS="urn:AnalyzeOrder"
languageSpecificType="java:com.chnic.bean.OrderBean"/>
</service>
</deployment>
唯一不同的就是多了<beabMapping>這個(gè)節(jié)點(diǎn)。qname 表示 XML 規(guī)范中定義的限定名稱,他由名稱空間 URI、本地部分和前綴組成。除了本地部分其他都不是必須的另外QName是不可變的。xmlns后面的myNS是必須的。具體根據(jù)前面所指定的qname來決定。之后可以隨意命名一個(gè)namespace。最后的languageSpecificType指定的是你傳遞的對象類型。第一個(gè)屬性的本地部分和第二個(gè)節(jié)點(diǎn)你自定義的命名空間會(huì)組成一個(gè)新的QName,并將你要傳輸?shù)膶ο髆apping是上去。
發(fā)布這個(gè)webservice,編寫測試代碼
- String targetEendPoint = "http://localhost:8080/axis/services/CheckOrder";
- OrderBean order = new OrderBean();
- order.setName("Beckham");
- order.setAge(32);
- String [] items = new String[] { "Ipod", "ThinkPad" };
- int [] price = new int [] { 999, 5000 };
- order.setItems(items);
- order.setPrice(price);
- order.setChecked(false);
- System.out.println(order.isChecked());
- Service service = new Service();
- Call call = (Call) service.createCall();
- QName qn = new QName("urn:AnalyzeOrder", "Order" );
- call.registerTypeMapping(OrderBean.class, qn,
- new org.apache.axis.encoding.ser.BeanSerializerFactory(OrderBean.class, qn),
- new org.apache.axis.encoding.ser.BeanDeserializerFactory(OrderBean.class, qn));
- call.setTargetEndpointAddress( new java.net.URL(targetEendPoint) );
- call.setOperationName( new QName("CheckOrder", "process") );
- call.addParameter( "arg1", qn, ParameterMode.IN );
- call.setReturnClass(OrderBean.class);
- OrderBean result = (OrderBean) call.invoke( new Object[] {order} );
- System.out.println("Success...");
- System.out.println(result.isChecked())
String targetEendPoint = "http://localhost:8080/axis/services/CheckOrder";
OrderBean order = new OrderBean();
order.setName("Beckham");
order.setAge(32);
String [] items = new String[] { "Ipod", "ThinkPad" };
int [] price = new int [] { 999, 5000 };
order.setItems(items);
order.setPrice(price);
order.setChecked(false);
System.out.println(order.isChecked());
Service service = new Service();
Call call = (Call) service.createCall();
QName qn = new QName("urn:AnalyzeOrder", "Order" );
call.registerTypeMapping(OrderBean.class, qn,
new org.apache.axis.encoding.ser.BeanSerializerFactory(OrderBean.class, qn),
new org.apache.axis.encoding.ser.BeanDeserializerFactory(OrderBean.class, qn));
call.setTargetEndpointAddress( new java.net.URL(targetEendPoint) );
call.setOperationName( new QName("CheckOrder", "process") );
call.addParameter( "arg1", qn, ParameterMode.IN );
call.setReturnClass(OrderBean.class);
OrderBean result = (OrderBean) call.invoke( new Object[] {order} );
System.out.println("Success...");
System.out.println(result.isChecked())
從控制臺(tái)輸出一些信息以便測試,里面大多代碼都應(yīng)該見過。new QName和之后的registerTypeMapping方法也是在實(shí)現(xiàn)我上面那段黑體字的內(nèi)容。之后注冊完參數(shù)和返回值類型運(yùn)行。
會(huì)發(fā)現(xiàn)在tomcat控制臺(tái)和本地控制臺(tái)都會(huì)輸出測試結(jié)果,值得注意的是checked這個(gè)屬性在傳入之前是false屬性,傳入之后我們改變了他的屬性變?yōu)閠rue。返回之后在本地控制臺(tái)打印出來也為true。
事實(shí)上Axis除了可以傳輸JavaBean之外還可以傳輸一些自定義的類型。比如List、Map和時(shí)間日期類型。Axis也為他們提供了專門的SerializerFactory和DeserializerFactory。這些工廠類會(huì)產(chǎn)生串行化工具去序列化相應(yīng)的對象。更多的Factory Object可以在org.apache.axis.encoding.ser下面找到。
對于自定義序列化,Axis也提供了相對性的配置節(jié)點(diǎn)。具體配置如下:
- <typeMapping qname="ns:local" xmlns:ns="someNamespace"
- languageSpecificType="java:my.java.thingy"
- serializer="my.java.Serializer"
- deserializer="my.java.DeserializerFactory"
- encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<typeMapping qname="ns:local" xmlns:ns="someNamespace"
languageSpecificType="java:my.java.thingy"
serializer="my.java.Serializer"
deserializer="my.java.DeserializerFactory"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
typeMapping的前三個(gè)屬性和上面講的beanMapping都一樣。不一樣的是后三個(gè)。serializer指定的是串行化類,dserializer指定的是反串行化類。最后一個(gè)指定的編碼方式。其實(shí)對于typeMapping來說beanMapping只不過是他的一個(gè)簡化版而已。因?yàn)閎eanMapping的串行化和反串行化工廠類都是固定的,而編碼方式也是固定的。
因?yàn)閠ypemapping和beanMapping很相似,在這里就不再寫demo了。 有些人也許會(huì)問,既然能串行化對象那能不能“串行化”文件呢?這個(gè)問題留著下次再說吧。今天米動(dòng)力了。
小白