這幾天貌似戰鬥力無窮,趁着有精力就多更新兩篇。隨着對Axis的研究加深,越感覺webservice是個很好玩的東西。這篇說一下如何傳遞一個JavaBean和你自己的一個special Object。
在 第一篇介紹Axis的文章裏,我們做了一個簡單的webservice,我們client side傳遞了String和int類型的數據給service object。Service處理之後返回處理結果給Client。對於大多數需求,那個demo顯然已經足夠應付了。但是如果client端需要傳輸一 個對象給server,那麼那個demo就顯得力不從心了。Axis中提供了遠程傳輸對象的方法,通過那些方法我們同樣可以隨心的傳遞自己的對象。
我們先從傳遞一個JavaBean開始,首先編寫一個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;
- }
- }
這個JavaBean的前4個屬性都很清楚,要解釋一下最後一個。因爲這個JavaBean被傳遞到Service端處理之後要接着被傳回,用來示例webservce傳進和傳出。這個變量用來區別傳進和傳出的差別。解釋完我們來看下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;
- }
- }
Service Object的代碼很簡單,就不解釋了。慣例,我們來編寫發佈文件。
- <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>這個節點。qname 表示 XML 規範中定義的限定名稱,他由名稱空間 URI、本地部分和前綴組成。除了本地部分其他都不是必須的另外QName是不可變的。xmlns後面的myNS是必須的。具體根據前面所指定的 qname來決定。之後可以隨意命名一個namespace。最後的languageSpecificType指定的是你傳遞的對象類型。第一個屬性的本地部分和第二個節點你自定義的命名空間會組成一個新的QName,並將你要傳輸的對象mapping是上去。
發佈這個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())
從控制檯輸出一些信息以便測試,裏面大多代碼都應該見過。new QName和之後的registerTypeMapping方法也是在實現我上面那段黑體字的內容。之後註冊完參數和返回值類型運行。
會發現在tomcat控制檯和本地控制檯都會輸出測試結果,值得注意的是checked這個屬性在傳入之前是false屬性,傳入之後我們改變了他的屬性變爲true。返回之後在本地控制檯打印出來也爲true。
事 實上Axis除了可以傳輸JavaBean之外還可以傳輸一些自定義的類型。比如List、Map和時間日期類型。Axis也爲他們提供了專門的 SerializerFactory和DeserializerFactory。這些工廠類會產生串行化工具去序列化相應的對象。更多的Factory Object可以在org.apache.axis.encoding.ser下面找到。
對於自定義序列化,Axis也提供了相對性的配置節點。具體配置如下:
- <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的前三個屬性和上面講的beanMapping都一樣。不一樣的是後三個。serializer指定的是串行化類, dserializer指定的是反串行化類。最後一個指定的編碼方式。其實對於typeMapping來說beanMapping只不過是他的一個簡化版 而已。因爲beanMapping的串行化和反串行化工廠類都是固定的,而編碼方式也是固定的。
因爲typemapping和beanMapping很相似,在這裏就不再寫demo了。 有些人也許會問,既然能串行化對象那能不能“串行化”文件呢?這個問題留着下次再說吧。今天米動力了