這是AXIS學(xué)習(xí)筆記的最后一篇。在前面我們討論了最簡(jiǎn)單的HelloWorld服務(wù),客戶端并沒(méi)有向服務(wù)器端傳遞參數(shù),現(xiàn)在我們來(lái)傳JavaBean。當(dāng)然,也可以傳遞你自己定義的JAVA類,但那樣你必須自己創(chuàng)建專門的XML序列化器和反序列化器;而對(duì)JavaBean,AXIS提供了現(xiàn)成的序列化器。(有人說(shuō):懶惰是程序員最大的美德)
一、服務(wù)器端
1、CLASS類兩個(gè)Order.class,OrderTest.class,位于%TOMCAT_HOME%\webapps\axis\WEB-INF\classes下
這兩個(gè)類都直接給出源碼,不再說(shuō)明
Order.java
public class Order {
private String id;
private String name;
public void setId(String id){
this.id=id;
}
public String getId(){
return id;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
}
OrderTest.java
public class OrderTest {
public Order returnOrder(Order order){
Order newOrder=new Order();
if(order.getId().equals("1"))
newOrder.setName("ronghao");
else newOrder.setName("haorong");
return newOrder;
}
}
2、修改服務(wù)器端配置文件server-config.wsdd
在server-config.wsdd中相應(yīng)位置添加以下代碼
<service name="Order" provider="java:RPC">
<parameter name="allowedMethods" value="returnOrder"/>
<parameter name="className" value="OrderTest"/>
<beanMapping languageSpecificType="java:Order" qname="ns1:Order"
xmlns:ns1="urn:BeanService"/>
</service>
可以看到和前面的發(fā)布服務(wù)代碼相比僅多了一行代碼
<beanMapping languageSpecificType="java:Order" qname="ns1:Order"
xmlns:ns1="urn:BeanService"/>
languageSpecificType屬性指定JavaBean類文件位置,例如:
languageSpecificType="java:com.ronghao.axis.Order"
qname屬性指定JavaBean類的名字
其他是固定的。
二、客戶端
客戶端類文件一個(gè)OrderClient.class,代碼如下(變化的部分加注釋):
public class OrderClient
{
public static void main(String args[])
throws Exception
{
String endpoint = "http://localhost:8080/axis/services/Order"; //服務(wù)所在位置
Order order=new Order(); //JavaBean
order.setId("1");
Service service = new Service();
Call call = (Call)service.createCall();
//注冊(cè)JavaBean,注意和server-config.wsdd中的配置代碼比較
QName qn = new QName("urn:BeanService", "Order");
call.registerTypeMapping(Order.class, qn, new BeanSerializerFactory(Order.class, qn),
new BeanDeserializerFactory(Order.class, qn));
String name="no!";
try
{
call.setTargetEndpointAddress(new URL(endpoint));
//調(diào)用的服務(wù)器端方法
call.setOperationName(new QName("Order", "returnOrder"));
//設(shè)定傳入的參數(shù),這里qn即Order.class
call.addParameter("arg1", qn, ParameterMode.IN);
//設(shè)定返回的參數(shù)是Order.class
call.setReturnType(qn, Order.class);
Order result = (Order)call.invoke(new Object[] {
order
});
if(result != null)
name = result.getName();
}
catch(Exception e)
{
System.err.println(e);
}
System.out.println(name);
}
}
OK!運(yùn)行一下,就可以看到返回了"ronghao"。
和上一篇文章一樣,我們不容許在網(wǎng)絡(luò)中傳遞XML是明文,于是需要加密和驗(yàn)證。這里我們繼續(xù)采用上次所講的框架。(已打包成ws-axis.jar)
一、修改服務(wù)器端配置文件server-config.wsdd(和上一文章一模一樣!不再羅嗦)
在server-config.wsdd中相應(yīng)位置添加以下代碼
<requestFlow>
<handler type="soapmonitor"/>
<handler type="java:com.ronghao.WSAxis.WSServerRequestHandler">
<parameter name="keyStoreFile" value="f:\server.keystore"/>
<parameter name="trustStoreFile" value="f:\server.truststore"/>
<parameter name="keyStorePassword" value="changeit"/>
<parameter name="keyAlias" value="Server"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="certAlias" value="clientkey"/>
</handler>
</requestFlow>
<responseFlow>
<handler type="soapmonitor"/>
<handler type="java:com.ronghao.WSAxis.WSServerResponseHandler">
<parameter name="keyStoreFile" value="f:\server.keystore"/>
<parameter name="trustStoreFile" value="f:\server.truststore"/>
<parameter name="keyStorePassword" value="changeit"/>
<parameter name="keyAlias" value="Server"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="certAlias" value="clientkey"/>
</handler>
</responseFlow>
二、客戶端(區(qū)別就在這里,注意?。。?/span>
首先在這里要說(shuō)一下,客戶端代碼編寫困擾了我很長(zhǎng)一段時(shí)間(整整一天),因?yàn)樗⒉幌笪蚁胂蟮哪敲春?jiǎn)單,當(dāng)然解決起來(lái)還是挺簡(jiǎn)單的:)問(wèn)題的解決經(jīng)歷了三個(gè)階段
第一階段:
在這個(gè)階段我想當(dāng)然的在OrderClient.class中加入了如下代碼:
WSClientHandler handler=new WSClientRequestHandler();//注意新加的HANDLER
handler.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
WSClientHandler handlee=new WSClientResponseHandler();//注意新加的HANDLER
handlee.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
call.setClientHandlers(handler,handlee);//添加Handler
這個(gè)方法也是我在上一文章里介紹的,結(jié)果拋出以下異常:
faultString: org.xml.sax.SAXException: Deserializing parameter
'newProfileReturn': could not find deserializer for type
{urn:BeanService Order}SerializableProfile
也就是說(shuō)不能正常解析XML文件,于是理所當(dāng)然的郁悶了,覺(jué)得代碼中肯定漏設(shè)了CALL的一個(gè)屬性,于是查看AXIS的源代碼,沒(méi)有結(jié)果!轉(zhuǎn)機(jī)出現(xiàn)在下面一行代碼,在不斷的拋出異常中我修改了代碼
將call.setClientHandlers(handler,handlee);改為
call.setClientHandlers(null,null);
結(jié)果程序還是拋出同樣的異常,于是意識(shí)到這可能是AXIS的一個(gè)BUG,為證明這一點(diǎn),我將下面的Handler初始化代碼刪除
WSClientHandler handler=new WSClientRequestHandler();//注意新加的HANDLER
handler.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
WSClientHandler handlee=new WSClientResponseHandler();//注意新加的HANDLER
handlee.setInitialization("f:/client.keystore","changeit","Client","changeit",
"f:/client.truststore","changeit","serverkey");//初始化
結(jié)果還是拋出同樣的異常,果然是BUG!得到這個(gè)結(jié)論后去了apache AXIS主頁(yè),在問(wèn)題列表中見(jiàn)到了完全一樣問(wèn)題的提交,但沒(méi)有解答(暈?。?/span>
最后得到了結(jié)論:call的setClientHandlers()方法只有當(dāng)call處理簡(jiǎn)單的數(shù)據(jù)類型,如String,int等等才能正常使用!
(當(dāng)然,如果你對(duì)這個(gè)問(wèn)題有不同的見(jiàn)解,歡迎和我聯(lián)系。或許我錯(cuò)了,但程序不運(yùn)行是真的:))
第二階段:
開(kāi)始在google上找問(wèn)題的解決方法,這也是我的習(xí)慣:)。找了一個(gè)類似問(wèn)題的討論,地址如下:
http://marc.theaimsgroup.com/?l=axis-user&m=111259980822735&w=2
他們的解決方法是Handler繼承于javax.xml.rpc.handler.Handler,然后在程序里動(dòng)態(tài)注冊(cè)而在我的ws-axis.jar里Handler繼承于org.apache.axis.handlers.BasicHandler。當(dāng)然,
javax.xml.rpc.handler.Handler是org.apache.axis.handlers.BasicHandler的老爸,但在程序里老爸和兒子之間卻不能很好的兼容,這也許就是所謂的代溝??無(wú)奈中重新寫了Handler,但在運(yùn)行中卻拋出異常,提示message在被invoke的時(shí)候已被更改。Handler的作用就是來(lái)更改message的??!
我知道很多程序采用的就是這種方法,但我好象怎么修改都拋出上述異常。
第三階段
既然在程序里動(dòng)態(tài)注冊(cè)Handler行不通,于是決定寫個(gè)單獨(dú)的配置文件來(lái)注冊(cè)Handler。如果這種方法不幸失敗就返回第二階段。好馬為什么不吃回頭草??
1、ws-axis.jar中修改WSClientHandler.class,修改后如下,我想你一看就明白為何修改
public class WSClientHandler extends BasicHandler{
protected String keyStoreFile ;
protected String keyStoreType ="JKS";
protected String keyStorePassword ;
protected String keyAlias ;
protected String keyEntryPassword ;
protected String trustStoreFile ;
protected String trustStoreType = "JKS";
protected String trustStorePassword ;
protected String certAlias ;
public void init() {
keyStoreFile = (String)getOption("keyStoreFile");
if(( keyStoreFile== null) )
System.err.println("Please keyStoreFile configured for the Handler!");
trustStoreFile = (String)getOption("trustStoreFile");
if(( trustStoreFile== null) )
System.err.println("Please trustStoreFile configured for the Handler!");
keyStorePassword = (String)getOption("keyStorePassword");
if(( keyStorePassword== null) )
System.err.println("Please keyStorePassword configured for the Handler!");
keyAlias = (String)getOption("keyAlias");
if(( keyAlias== null) )
System.err.println("Please keyAlias configured for the Handler!");
keyEntryPassword = (String)getOption("keyEntryPassword");
if(( keyEntryPassword== null) )
System.err.println("Please keyEntryPassword configured for the Handler!");
trustStorePassword = (String)getOption("trustStorePassword");
if(( trustStorePassword== null) )
System.err.println("Please trustStorePassword configured for the Handler!");
certAlias = (String)getOption("certAlias");
if ((certAlias==null))
System.err.println("Please certAlias configured for the Handler!");
if ((getOption("keyStoreType")) != null)
keyStoreType = (String)getOption("keyStoreType");
if ((getOption("trustStoreType")) != null)
trustStoreType = (String)getOption("trustStoreType");
}
public void invoke(MessageContext messageContext) throws AxisFault {
//do nothing now!
}
public void onFault(MessageContext msgContext) {
System.out.println("處理錯(cuò)誤,這里忽略!");
}
}
2、寫客戶端的配置代碼client-config.wsdd,如下:
<?xml version="1.0" encoding="UTF-8"?>
<deployment name="defaultClientConfig"
xmlns="http://xml.apache.org/axis/wsdd/"
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
<transport name="http"
pivot="java:org.apache.axis.transport.http.HTTPSender"/>
<transport name="local"
pivot="java:org.apache.axis.transport.local.LocalSender"/>
<transport name="java"
pivot="java:org.apache.axis.transport.java.JavaSender"/>
<globalConfiguration>
<requestFlow>
<handler type="java:com.ronghao.WSAxis.WSClientRequestHandler">
<parameter name="keyStoreFile" value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.keystore"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="certAlias" value="serverkey"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="trustStoreFile" value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.truststore"/>
<parameter name="keyAlias" value="Client"/>
<parameter name="keyStorePassword" value="changeit"/>
</handler>
</requestFlow>
<responseFlow>
<handler type="java:com.ronghao.WSAxis.WSClientResponseHandler">
<parameter name="keyStoreFile" value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.keystore"/>
<parameter name="keyEntryPassword" value="changeit"/>
<parameter name="certAlias" value="serverkey"/>
<parameter name="trustStorePassword" value="changeit"/>
<parameter name="trustStoreFile" value="D:\Tomcat5.5\webapps\axis\WEB-INF\client.truststore"/>
<parameter name="keyAlias" value="Client"/>
<parameter name="keyStorePassword" value="changeit"/>
</handler>
</responseFlow>
</globalConfiguration>
</deployment>
同樣不再解釋,不明白可以參考我的上一篇文章
3、修改OrderClient.class
在OrderClient.class中加入了如下代碼:
EngineConfiguration conf =
new FileProvider("F:\\Tomcat\\webapps\\axis\\WEB-INF\\client-config.wsdd");//位置
Service service = new Service(conf);
當(dāng)然記得導(dǎo)入
import org.apache.axis.EngineConfiguration;
import org.apache.axis.configuration.FileProvider;
運(yùn)行一下,返回"ronghao",搞定!
注意:這次我把OrderClient.class的調(diào)用放到了一個(gè)JSP文件中而不是jbuilder中,因?yàn)橛?/span>client-config.wsdd,所以你必須有完整的WEB程序發(fā)布到TOMCAT中,否則會(huì)報(bào)找不到
相應(yīng)文件。
http://m.tkk7.com/ronghao 榮浩原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處:)
posted on 2007-06-12 16:25
ronghao 閱讀(5342)
評(píng)論(3) 編輯 收藏 所屬分類:
SOA、BPM