xstream与resttemplate的联合使用
来源:互联网 发布:ubuntu拷贝文件夹 编辑:程序博客网 时间:2024/04/30 08:32
最近做微信支付开发,接口都是xml数据,决定应xstream。用之后发现spring的默认XStreamMarshaller不能达到要求,所以做了自定义
配置如下
这里有两个自己实现类CustomXStreamMarshaller和CustomXppDriver<bean id="xStreamMarshaller" class="cloudolp.CustomXStreamMarshaller"> <property name="annotatedClasses"> <array> <value>com.cloudolp.base.SmsResponse</value> <value>com.cloudolp.base.weixinpay.UnifiedorderRequest</value> <value>com.cloudolp.base.weixinpay.UnifiedorderResponse</value> </array> </property> <property name="streamDriver"> <bean class="cloudolp.CustomXppDriver"> <constructor-arg> <bean class="com.thoughtworks.xstream.io.naming.NoNameCoder"/> </constructor-arg> </bean> </property></bean>
package cloudolp;import com.thoughtworks.xstream.XStream;import com.thoughtworks.xstream.annotations.XStreamAlias;import com.thoughtworks.xstream.core.util.QuickWriter;import com.thoughtworks.xstream.io.*;import com.thoughtworks.xstream.io.naming.NameCoder;import com.thoughtworks.xstream.io.xml.*;import java.io.Writer;import java.lang.reflect.Field;import org.springframework.oxm.xstream.XStreamMarshaller;/** * 增加ignoreUnknownElements */public class CustomXStreamMarshaller extends XStreamMarshaller { private boolean ignoreUnknow=false; public CustomXStreamMarshaller() { super(); } public void setIgnoreUnknow(boolean ignoreUnknow) { this.ignoreUnknow = ignoreUnknow; } @Override protected void customizeXStream(XStream xstream) { if(ignoreUnknow){ xstream.ignoreUnknownElements(); } }}这个类直接继承spring默认实现的XStreamMarshaller ,增加了一个选项:反序列化时是否忽略对象中不存在的属性。微信返回的xml中的很多字段我是不需要的,如果没加入这个选项,自定义的bean中必须包含所有xml中的标签,否则反序列换出错。
package cloudolp;import com.thoughtworks.xstream.annotations.XStreamAlias;import com.thoughtworks.xstream.core.util.QuickWriter;import com.thoughtworks.xstream.io.HierarchicalStreamWriter;import com.thoughtworks.xstream.io.naming.NameCoder;import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;import com.thoughtworks.xstream.io.xml.XppDriver;import java.io.Writer;import java.lang.reflect.Field;/** * Created by chao.zeng on 2016/10/20. */public class CustomXppDriver extends XppDriver { public CustomXppDriver(){ super(); } public CustomXppDriver(NameCoder nameCoder){ super(nameCoder); } @Override public HierarchicalStreamWriter createWriter(Writer out) { return new PrettyPrintWriter(out,getNameCoder()) { boolean cdata = false; Class<?> targetClass = null; private boolean needCDATA(Class<?> targetClass, String fieldAlias){ boolean cdata = false; //first, scan self cdata = existsCDATA(targetClass, fieldAlias); if(cdata) return cdata; //if cdata is false, scan supperClass until java.lang.Object Class<?> superClass = targetClass.getSuperclass(); while(!superClass.equals(Object.class)){ cdata = existsCDATA(superClass, fieldAlias); if(cdata) return cdata; superClass = superClass.getClass().getSuperclass(); } return false; } private boolean existsCDATA(Class<?> clazz, String fieldAlias){ //scan fields Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { //1. exists XStreamCDATA if(field.getAnnotation(XStreamCDATA.class) != null ){ XStreamAlias xStreamAlias = field.getAnnotation(XStreamAlias.class); //2. exists XStreamAlias if(null != xStreamAlias){ if(fieldAlias.equals(xStreamAlias.value()))//matched return true; }else{// not exists XStreamAlias if(fieldAlias.equals(field.getName())) return true; } } } return false; } @Override public void startNode(String name,@SuppressWarnings("rawtypes") Class clazz) { super.startNode(name, clazz); //业务处理,对于用XStreamCDATA标记的Field,需要加上CDATA标签 if(!name.equals("xml")){ cdata = needCDATA(targetClass, name); }else{ targetClass = clazz; } } @Override protected void writeText(QuickWriter writer, String text) { if (cdata) { if(text!=null && !text.startsWith("<![CDATA[")){ writer.write("<![CDATA["+text+"]]>"); }else{ writer.write("text"); } } else { writer.write(text); } } }; }}
package cloudolp;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * Created by chao.zeng on 2016/10/20. */@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD})public @interface XStreamCDATA {}
有时候我们的标签的内容可能会包含特殊字符,这就需要使用<![CDATA[]]>将内容包裹起来,微信支付的很多标签都要求用<![CDATA[]]>包裹,这个自定义的driver就是实现此功能。
这里还有一个需要注意的类NoNameCoder,这个类不会把下划线转换成双下划线,而默认的是XmlFriendlyNameCoder会变成双下划线,微信支付的接口的很多XML都是a_b的结构,我们的bean属性的命名一一般是aB,所以会加上别名@XStreamAlias("a_b"),这时候一定要指定NoNameCoder,否则生成的标签是带双下划线的,导致接口调用失败
0 0
- xstream与resttemplate的联合使用
- 联合的定义与使用
- Xstream的使用
- xstream插件的使用
- 关于XStream的使用
- xstream的别名使用
- Xstream的使用
- Xstream的简单使用
- XStream的简单使用
- xstream的简单使用
- XStream的使用
- XStream的简单使用
- RestTemplate使用
- RestTemplate使用
- 使用XStream, 对于java object与xml之间的转换
- 使用XStream实现xml与JavaBean之间的转换
- 使用 XStream 实现 Java 对象与 XML 的相互转换
- 使用XStream是实现XML与Java对象的…
- CENTOS 6.5 配置YUM安装NGINX
- Springboot 之 文件结构和配置文件
- 第22课:<img>标签、表单标签(form)
- NRF51822开发中常见问题和解决办法汇总----持续添加
- Springboot 之 自定义配置文件及读取配置文件
- xstream与resttemplate的联合使用
- 第八周项目3-顺序串算法
- 并发编程基础
- Springboot 之 单元测试
- 从外网远程控制家里的电视盒子,无需设置路由
- 【第六周 项目6-求解8皇后问题的程序】
- Windows 7 Ultra Edit 运行错误 解决方法
- Springboot 之 多配置文件
- POJ 2296Map Labeler 2-sat + 矩阵相交