CXF 中引入了一个 annotation: @DataBinding(org.apache.cxf.annotations.DataBinding), 可以用于标注一个WebService接口,指明特定的DataBinding, 从而避免使用默认的DataBinding(当然也可以通过配置文件的形式指定DataBinding,而这种annotation的方式要简便一些)。
同时,程序员可以编写自己的DataBinding类,来完全控制数据绑定的方式。
JAXB 和 AegisDataBinding都有自己的不足之处,自己编写DataBinding,在某些条件下可以弥补这些现有的DataBinding的不足。
例如,如果WebService的接口方法中,所有参数和返回值都是Serializable的,那么可以自己定义一个SerializableDatabinding,这样就不必关心参数、返回值的类型,是否有无参数的构造方法、是否是泛型等问题;同时,网络上传输的不再是明文。虽然没有加密,但也有一定程度的保密作用。
下面就是这个SerializableDatabinding的所需代码,有了这些代码就可以在特定的WebService接口上使用@DataBinding来指定这个新的DataBinding了。例如:
@WebService
@DataBinding(SerializableZipDatabinding.class)
public interface IDBUtilSvc {
public CachedRowSet getRowSetBySql(String asConnKey, StringasSelectSql,int aiPageSize,int aiPageIndex)
throws SQLException;
…
}
- SerializableDatabinding.java
package cn.yanggq.webservice.databinding.serializer; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import org.apache.cxf.databinding.DataReader; import org.apache.cxf.databinding.DataWriter; import org.apache.cxf.service.Service; import org.apache.log4j.Logger; import org.w3c.dom.Node; /** * 这个类提供一种简单的WebService的数据邦定方式,凡是Serializable的对象都可以作为参数或者返回值转递。 * <BR>计划还要支持数据压缩。 * <br><B>注</B>:目前可能还不成熟。 * @author stoney(YangGQ) * */ //public class AnyDatabinding implements DataBinding { public class SerializableDatabinding extends org.apache.cxf.databinding.AbstractDataBinding{ static Logger logger = Logger.getLogger(SerializableDatabinding.class); protected Class<?> supportedReaderFormat[]={SerializableDataReader.class, Node.class,XMLStreamReader.class}; protected Class<?> supportedWriterFormat[]={SerializableDataWriter.class, Node.class,XMLStreamWriter.class}; @Override public <T> DataReader<T> createReader(Class<T> cls) { logger.trace("Getting DataReader of " +cls); return new SerializableDataReader<T>(); } @Override public <T> DataWriter<T> createWriter(Class<T> cls) { logger.trace("Getting DataWriter of " +cls); return new SerializableDataWriter<T>(); } @Override public Class<?>[] getSupportedReaderFormats() { return supportedReaderFormat; } @Override public Class<?>[] getSupportedWriterFormats() { return supportedWriterFormat; } @Override public void initialize(Service service) { //Do Nothing? } } |
- SerializableDataReader.java
package cn.yanggq.webservice.databinding.serializer; import java.util.Collection; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamReader; import javax.xml.validation.Schema; import org.apache.cxf.databinding.DataReader; import org.apache.cxf.message.Attachment; import org.apache.cxf.service.model.MessagePartInfo; import org.apache.log4j.Logger; import com.ordinov.application.exception.OAFRuntimeException; import com.ordinov.util.DataProcessor; import com.ordinov.util.Serializer; /** * Serializable数据的Reader。 * @author stoney(YangGQ) * * @param <T> */ public class SerializableDataReader<T> implements DataReader<T>{ private static Logger logger = Logger.getLogger(SerializableDataReader.class); private boolean dataCompressed = false; public SerializableDataReader() { } public SerializableDataReader(boolean abDataCompressed) { dataCompressed = abDataCompressed; } @Override public Object read(Object input) { logger.trace("reading "+ input); if (input instanceof XMLStreamReader ){ return read(null,(XMLStreamReader)input); }else{ throw new OAFRuntimeException("不支持的input:"+input); } } @Override public Object read(MessagePartInfo part, Object input) { // logger.trace("reading "+ input +"\n\tMessagePart:"+part); if (input instanceof XMLStreamReader ){ return read(part,(XMLStreamReader)input); }else{ throw new OAFRuntimeException("不支持的input:"+input); } } public Object read(MessagePartInfo part, XMLStreamReader reader) { Object loRet = null; try { String lsEleName = reader.getLocalName(); logger.trace("\tReading data of (LocalName) "+lsEleName); String lsData = reader.getElementText(); // logger.trace("\tElement Text="+lsData); byte sBytes[] = (new sun.misc.BASE64Decoder()).decodeBuffer( lsData ); if (dataCompressed){ // logger.trace("\tData compressed, deCompressing..."); sBytes = DataProcessor.DeCompressData(sBytes); } Serializer s = new Serializer(); loRet = s.deSerializeAny(sBytes); logger.trace("\t\tElement '"+ lsEleName +"' Class:"+ (loRet!=null?loRet.getClass():null)+", Value="+loRet); if(reader.hasNext()) reader.next();//非常关键!不调用此方法只能读取一个参数arg0(不知何故?本来理解应该是外部控制多次调用的) } catch (Exception e) { throw new OAFRuntimeException("无法读取数据并转换为对象",e); } return loRet; } @Override public Object read(QName elementQName, Object input, Class type) { logger.trace("reading "+ input +"\t\nQName:"+elementQName +"\n\tAs Type:"+type); if (input instanceof XMLStreamReader ){ return read(null,(XMLStreamReader)input); }else{ throw new OAFRuntimeException("不支持的input:"+input); } } @Override public void setAttachments(Collection<Attachment> attachments) { logger.trace("setAttachments: "+attachments); } @Override public void setProperty(String prop, Object value) { logger.trace("setProperty: "+prop + "->" + value); } @Override public void setSchema(Schema s) { logger.trace("setSchema: "+s); } public boolean isDataCompressed() { return dataCompressed; } public void setDataCompressed(boolean dataCompressed) { this.dataCompressed = dataCompressed; } } |
- SerializableDataWriter.java
package cn.yanggq.webservice.databinding.serializer; import java.util.Collection; import javax.xml.stream.XMLStreamWriter; import javax.xml.validation.Schema; import org.apache.cxf.aegis.xml.stax.ElementWriter; import org.apache.cxf.databinding.DataWriter; import org.apache.cxf.message.Attachment; import org.apache.cxf.service.model.MessagePartInfo; import org.apache.log4j.Logger; import com.ordinov.application.exception.OAFRuntimeException; import com.ordinov.util.DataProcessor; import com.ordinov.util.Serializer; /** * Serializable数据的Writer。 * * @author stoney(YangGQ) * * @param <T> */ public class SerializableDataWriter<T> implements DataWriter<T>{ private static Logger logger = Logger.getLogger(SerializableDataWriter.class); private boolean dataCompressed = false; public SerializableDataWriter() {} public SerializableDataWriter(boolean abDataCompressed) { dataCompressed = abDataCompressed; } @Override public void write(Object obj, Object output) { logger.trace("writing '"+ obj + "' to "+output); } @Override public void write(Object obj, MessagePartInfo part, Object output) { // logger.trace("writing '"+ obj + "' to "+output + // "\n\tMessagePartIngo:"+part); if (output instanceof XMLStreamWriter){ this.write(obj, part, (XMLStreamWriter)output); }else{ throw new OAFRuntimeException("不支持的output:"+output); } } public void write(Object obj, MessagePartInfo part, XMLStreamWriter output) { try { logger.trace("writing data '"+ obj + "', LocalName: "+part.getElementQName()); Serializer s = new Serializer(); byte sBytes[] = s.serializeAny(obj); if (dataCompressed){ // logger.trace("\tData should be compressed, compressing..."); sBytes = DataProcessor.CompressData(sBytes); } String lsData = (new sun.misc.BASE64Encoder()).encode( sBytes ); // output.writeAttribute("ENCODED_DATA", lsData); ElementWriter writer = new ElementWriter(output,part.getElementQName()); writer.writeValue(lsData); writer.close();//必须! }catch (Exception e){ throw new OAFRuntimeException("写对象时出错!",e); } } @Override public void setAttachments(Collection<Attachment> attachments) { logger.trace("setAttachments: "+attachments); } @Override public void setProperty(String key, Object value) { logger.trace("setProperty: "+key + "->" + value); } @Override public void setSchema(Schema s) { logger.trace("setSchema: "+s); } public boolean isDataCompressed() { return dataCompressed; } public void setDataCompressed(boolean dataCompressed) { this.dataCompressed = dataCompressed; } } |