整合xfire与struts2 (二)
二.关于xfire service 支持自定义对象的串行化:
如果你用jdk1.5以上版本和xfire1.2以上版本,不需要这一步,因为它会自动序列化。
但是如果你的程序是在jdk1.4的基础上运行的,就需要手工搞定了,解决这个问题的核心是一个名称为****.aegis.xml的映射文件。
例如:Xfire webService 返回一个自定义的wsResult对象。
1. WsResult类定义如下:
package com.jetsen.jmam32.services;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
public class wsResult {
private int errorCode;
private String errorString;
private String resultVal;
public wsResult(){
this.errorCode = 0;
this.errorString = "";
this.resultVal = "";
}
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getErrorString() {
return errorString;
}
public void setErrorString(String errorString) {
this.errorString = errorString;
}
public String getResultVal() {
return resultVal;
}
public void setResultVal(String resultVal) {
this.resultVal = resultVal;
}
}
注意:这个自定义类必须与service类和接口在同一个包下(稍后会解释原因),本例中,必须放到包com.jetsen.jmam32.services下;其次,该类成员必须是严格的类属性,使用getter,setter的语法读取或设置。(起初我想懒省事,直接把三个属性设成了public成员,结果不能串行化...)。
为了实现返回类型是wsResult,service的接口IJMAMCatalogMgrService代码如下:
package com.jetsen.jmam32.services;
publicinterface IJMAMCatalogMgrService {
public wsResult sayHello(String name);
}
Service实现类JMAMCatalogMgrService代码如下:
package com.jetsen.jmam32.services;
publicclass JMAMCatalogMgrService implements IJMAMCatalogMgrService {
public wsResult sayHello(String name){
wsResult ws = new wsResult();
String retStr = "Hello " + name;
ws.setResultVal(retStr);
return ws;
}
}
2. 在包com.jetsen.jmam32.services下新建映射文件:IJMAMCatalogMgrService.aegis.xml,
注意名称一定要是接口的名字(IJMAMCatalogMgrService)+ aegis.xml
该文件代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<mappings>
<mapping>
<method name="sayHello">
<return-type componentType="com.jetsen.jmam32.services.wsResult"/>
</method>
</mapping>
</mappings>
注意method名称(sayHello)和返回类型的名称(com.jetsen.jmam32.services.wsResult)。
3. 重启tomcat,然后打开http://localhost:8080/JMAM32/services/MAMCatalogMgrService?wsdl
你可以看到wsdl文件了,可以看到wsdl文件中的wsResult被串行化了:
<xsd:complexType name="wsResult">
<xsd:sequence>
<xsd:element minOccurs="0" name="errorCode" type="xsd:int" />
<xsd:element minOccurs="0" name="errorString" nillable="true" type="xsd:string" />
<xsd:element minOccurs="0" name="resultVal" nillable="true" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="sayHelloResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element maxOccurs="1" minOccurs="1" name="out" nillable="true" type="tns:wsResult" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
这里就要解释一下前面为什么要把wsResult类放在com.jetsen.jmam32.services包中了。如果不放在一个包中,wsResult串行化内容会被放在另一个名称空间(namespace)中,而不会同方法名放在一起。当然这是没问题的,问题出在IE 7上,IE 7的xmlhttprequest对象将会不识别返回的responseXml,直接报错! Firefox没有问题。我甚至试过IE 6的XMLHTTP 的activex控件也有这个问题。
大功告成!这样客户端就不会不认识web service返回的对象类型了。不过顺便说一句,这方面还是.net比较方便,会自动串行化你自定义的对象。