去掉xstream依赖
This commit is contained in:
@@ -1,15 +1,10 @@
|
||||
package com.foxinmy.weixin4j.api;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinHttpClient;
|
||||
import com.foxinmy.weixin4j.xml.Map2ObjectConverter;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
import com.thoughtworks.xstream.core.ClassLoaderReference;
|
||||
import com.thoughtworks.xstream.mapper.DefaultMapper;
|
||||
|
||||
/**
|
||||
* API基础
|
||||
@@ -23,21 +18,6 @@ import com.thoughtworks.xstream.mapper.DefaultMapper;
|
||||
*/
|
||||
public abstract class BaseApi {
|
||||
protected final WeixinHttpClient weixinClient = new WeixinHttpClient();
|
||||
protected final static XmlStream mapXstream = XmlStream.get();
|
||||
static {
|
||||
mapXstream.alias("xml", Map.class);
|
||||
mapXstream.registerConverter(new Map2ObjectConverter(new DefaultMapper(
|
||||
new ClassLoaderReference(XmlStream.class.getClassLoader()))));
|
||||
}
|
||||
|
||||
protected String map2xml(Map<?, ?> map) {
|
||||
return mapXstream.toXML(map).replaceAll("__", "_");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map<String, String> xml2map(String xml) {
|
||||
return mapXstream.fromXML(xml, Map.class);
|
||||
}
|
||||
|
||||
protected abstract ResourceBundle getWeixinBundle();
|
||||
|
||||
@@ -55,7 +35,7 @@ public abstract class BaseApi {
|
||||
m.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
protected String getConfigValue(String key) {
|
||||
return getWeixinBundle().getString(key);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,10 @@ public class WeixinException extends Exception {
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public WeixinException(Throwable e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.foxinmy.weixin4j.util.ErrorUtil;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
import com.thoughtworks.xstream.mapper.CannotResolveClassException;
|
||||
|
||||
public class WeixinHttpClient extends SimpleHttpClient {
|
||||
|
||||
@@ -155,7 +154,7 @@ public class WeixinHttpClient extends SimpleHttpClient {
|
||||
try {
|
||||
checkXml(response);
|
||||
return response;
|
||||
} catch (CannotResolveClassException ex) {
|
||||
} catch (IllegalArgumentException ex) {
|
||||
;
|
||||
}
|
||||
throw new WeixinException(response.getAsString());
|
||||
@@ -185,7 +184,7 @@ public class WeixinHttpClient extends SimpleHttpClient {
|
||||
XmlResult xmlResult = null;
|
||||
try {
|
||||
xmlResult = response.getAsXmlResult();
|
||||
} catch (CannotResolveClassException ex) {
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// <?xml><root><data..../data></root>
|
||||
String newXml = response.getAsString()
|
||||
.replaceFirst("<root>", "<xml>")
|
||||
@@ -194,7 +193,7 @@ public class WeixinHttpClient extends SimpleHttpClient {
|
||||
.replaceFirst("<retmsg>", "<return_msg>")
|
||||
.replaceFirst("</retmsg>", "</return_msg>")
|
||||
.replaceFirst("</root>", "</xml>");
|
||||
xmlResult = XmlStream.get(newXml, XmlResult.class);
|
||||
xmlResult = XmlStream.fromXML(newXml, XmlResult.class);
|
||||
response.setContent(newXml.getBytes(Consts.UTF_8));
|
||||
}
|
||||
response.setXmlResult(true);
|
||||
|
||||
@@ -43,12 +43,12 @@ public class WeixinResponse extends HttpResponse {
|
||||
if (isXmlResult) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> clazz = (Class<T>) typeReference.getType();
|
||||
return XmlStream.get(getAsString(), clazz);
|
||||
return XmlStream.fromXML(getAsString(), clazz);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public XmlResult getAsXmlResult() {
|
||||
return XmlStream.get(getAsString(), XmlResult.class);
|
||||
return XmlStream.fromXML(getAsString(), XmlResult.class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package com.foxinmy.weixin4j.http.weixin;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 调用接口返回xml格式
|
||||
@@ -15,25 +17,41 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class XmlResult implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6185313616955051150L;
|
||||
|
||||
@XStreamAlias("return_code")
|
||||
/**
|
||||
* 此字段是通信标识,非交易 标识,交易是否成功需要查 看 result_code 来判断非空
|
||||
*/
|
||||
@XmlElement(name = "return_code")
|
||||
@JSONField(name = "return_code")
|
||||
private String returnCode;// 此字段是通信标识,非交易 标识,交易是否成功需要查 看 result_code 来判断 非空
|
||||
@XStreamAlias("return_msg")
|
||||
private String returnCode;
|
||||
/**
|
||||
* 返回信息,如非 空,为错误原因 可能为空
|
||||
*/
|
||||
@XmlElement(name = "return_msg")
|
||||
@JSONField(name = "return_msg")
|
||||
private String returnMsg;// 返回信息,如非 空,为错误原因 可能为空
|
||||
@XStreamAlias("result_code")
|
||||
private String returnMsg;
|
||||
/**
|
||||
* 业务结果SUCCESS/FAIL 非空
|
||||
*/
|
||||
@XmlElement(name = "result_code")
|
||||
@JSONField(name = "result_code")
|
||||
private String resultCode;// 业务结果SUCCESS/FAIL 非空
|
||||
@XStreamAlias("err_code")
|
||||
private String resultCode;
|
||||
/**
|
||||
* 错误代码 可为空
|
||||
*/
|
||||
@XmlElement(name = "err_code")
|
||||
@JSONField(name = "err_code")
|
||||
private String errCode;// 错误代码 可为空
|
||||
@XStreamAlias("err_code_des")
|
||||
private String errCode;
|
||||
/**
|
||||
* 结果信息描述 可为空
|
||||
*/
|
||||
@XmlElement(name = "err_code_des")
|
||||
@JSONField(name = "err_code_des")
|
||||
private String errCodeDes;// 结果信息描述 可为空
|
||||
private String errCodeDes;
|
||||
|
||||
public XmlResult() {
|
||||
}
|
||||
@@ -47,36 +65,36 @@ public class XmlResult implements Serializable {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public void setReturnCode(String returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
}
|
||||
|
||||
public String getReturnMsg() {
|
||||
return StringUtil.isNotBlank(returnMsg) ? returnMsg : null;
|
||||
}
|
||||
|
||||
public void setReturnMsg(String returnMsg) {
|
||||
this.returnMsg = returnMsg;
|
||||
return returnMsg;
|
||||
}
|
||||
|
||||
public String getResultCode() {
|
||||
return resultCode;
|
||||
}
|
||||
|
||||
public void setResultCode(String resultCode) {
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
public String getErrCode() {
|
||||
return errCode;
|
||||
}
|
||||
|
||||
public void setErrCode(String errCode) {
|
||||
this.errCode = errCode;
|
||||
public String getErrCodeDes() {
|
||||
return errCodeDes;
|
||||
}
|
||||
|
||||
public String getErrCodeDes() {
|
||||
return StringUtil.isNotBlank(errCodeDes) ? errCodeDes : null;
|
||||
public void setReturnCode(String returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
}
|
||||
|
||||
public void setReturnMsg(String returnMsg) {
|
||||
this.returnMsg = returnMsg;
|
||||
}
|
||||
|
||||
public void setResultCode(String resultCode) {
|
||||
this.resultCode = resultCode;
|
||||
}
|
||||
|
||||
public void setErrCode(String errCode) {
|
||||
this.errCode = errCode;
|
||||
}
|
||||
|
||||
public void setErrCodeDes(String errCodeDes) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import java.util.Calendar;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
/**
|
||||
* 用FILE保存TOKEN
|
||||
@@ -21,7 +21,6 @@ import com.thoughtworks.xstream.XStream;
|
||||
* @see com.foxinmy.weixin4j.token.TokenCreator
|
||||
*/
|
||||
public class FileTokenHolder implements TokenHolder {
|
||||
private final XStream xstream;
|
||||
private final String tokenPath;
|
||||
private final TokenCreator tokenCreator;
|
||||
|
||||
@@ -32,11 +31,6 @@ public class FileTokenHolder implements TokenHolder {
|
||||
public FileTokenHolder(String tokenPath, TokenCreator tokenCreator) {
|
||||
this.tokenPath = tokenPath;
|
||||
this.tokenCreator = tokenCreator;
|
||||
xstream = new XStream();
|
||||
xstream.ignoreUnknownElements();
|
||||
xstream.autodetectAnnotations(true);
|
||||
xstream.alias("xml", Token.class);
|
||||
xstream.processAnnotations(Token.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,8 +42,8 @@ public class FileTokenHolder implements TokenHolder {
|
||||
long now_time = ca.getTimeInMillis();
|
||||
try {
|
||||
if (token_file.exists()) {
|
||||
token = (Token) xstream
|
||||
.fromXML(new FileInputStream(token_file));
|
||||
token = XmlStream.fromXML(new FileInputStream(token_file),
|
||||
Token.class);
|
||||
long expire_time = token.getTime()
|
||||
+ (token.getExpiresIn() * 1000) - 2;
|
||||
if (expire_time > now_time) {
|
||||
@@ -57,7 +51,7 @@ public class FileTokenHolder implements TokenHolder {
|
||||
}
|
||||
}
|
||||
token = tokenCreator.createToken();
|
||||
xstream.toXML(token, new FileOutputStream(token_file));
|
||||
XmlStream.toXML(token, new FileOutputStream(token_file));
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e.getMessage());
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@ package com.foxinmy.weixin4j.tuple;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 客服消息图文
|
||||
@@ -21,24 +22,24 @@ public class Article implements Serializable {
|
||||
/**
|
||||
* 图文消息标题
|
||||
*/
|
||||
@XStreamAlias("Title")
|
||||
@XmlElement(name = "Title")
|
||||
private String title;
|
||||
/**
|
||||
* 图文消息描述
|
||||
*/
|
||||
@JSONField(name = "description")
|
||||
@XStreamAlias("Description")
|
||||
@XmlElement(name = "Description")
|
||||
private String desc;
|
||||
/**
|
||||
* 图片链接,支持JPG、PNG格式,较好的效果为大图360*200,小图200*200
|
||||
*/
|
||||
@JSONField(name = "picurl")
|
||||
@XStreamAlias("PicUrl")
|
||||
@XmlElement(name = "PicUrl")
|
||||
private String picUrl;
|
||||
/**
|
||||
* 点击图文消息跳转链接
|
||||
* 点击图文消息跳转链接
|
||||
*/
|
||||
@XStreamAlias("Url")
|
||||
@XmlElement(name = "Url")
|
||||
private String url;
|
||||
|
||||
public Article(String title, String desc, String picUrl, String url) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.foxinmy.weixin4j.tuple;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 文件对象
|
||||
@@ -28,7 +29,7 @@ public class File implements NotifyTuple {
|
||||
* 上传后的微信返回的媒体ID
|
||||
*/
|
||||
@JSONField(name = "media_id")
|
||||
@XStreamAlias("MediaId")
|
||||
@XmlElement(name = "MediaId")
|
||||
private String mediaId;
|
||||
|
||||
public File(String mediaId) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.foxinmy.weixin4j.tuple;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 图片对象
|
||||
@@ -28,7 +29,7 @@ public class Image implements MassTuple, NotifyTuple {
|
||||
* 上传后的微信返回的媒体ID
|
||||
*/
|
||||
@JSONField(name = "media_id")
|
||||
@XStreamAlias("MediaId")
|
||||
@XmlElement(name = "MediaId")
|
||||
private String mediaId;
|
||||
|
||||
public Image(String mediaId) {
|
||||
|
||||
@@ -3,9 +3,10 @@ package com.foxinmy.weixin4j.tuple;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
/**
|
||||
* 图文对象(消息内容存储在微信后台)
|
||||
@@ -32,13 +33,13 @@ public class MpNews implements MassTuple, NotifyTuple {
|
||||
* 上传图文列表后微信返回的媒体ID
|
||||
*/
|
||||
@JSONField(name = "media_id")
|
||||
@XStreamAlias("MediaId")
|
||||
@XmlElement(name = "MediaId")
|
||||
private String mediaId;
|
||||
/**
|
||||
* 图文列表
|
||||
*/
|
||||
@JSONField(name = "articles")
|
||||
@XStreamOmitField
|
||||
@XmlTransient
|
||||
private List<MpArticle> articles;
|
||||
|
||||
public MpNews() {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.foxinmy.weixin4j.tuple;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 群发视频对象
|
||||
@@ -28,7 +29,7 @@ public class MpVideo implements MassTuple {
|
||||
* 上传视频后微信返回的媒体ID
|
||||
*/
|
||||
@JSONField(name = "media_id")
|
||||
@XStreamAlias("MediaId")
|
||||
@XmlElement(name = "MediaId")
|
||||
private String mediaId;
|
||||
|
||||
public MpVideo(String mediaId) {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package com.foxinmy.weixin4j.tuple;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 音乐对象
|
||||
@@ -27,31 +28,31 @@ public class Music implements NotifyTuple {
|
||||
/**
|
||||
* 音乐标题
|
||||
*/
|
||||
@XStreamAlias("Title")
|
||||
@XmlElement(name = "Title")
|
||||
private String title;
|
||||
/**
|
||||
* 音乐描述
|
||||
*/
|
||||
@JSONField(name = "description")
|
||||
@XStreamAlias("Description")
|
||||
@XmlElement(name = "Description")
|
||||
private String desc;
|
||||
/**
|
||||
* 音乐链接
|
||||
*/
|
||||
@JSONField(name = "musicurl")
|
||||
@XStreamAlias("MusicUrl")
|
||||
@XmlElement(name = "MusicUrl")
|
||||
private String musicUrl;
|
||||
/**
|
||||
* 高质量音乐链接,WIFI环境优先使用该链接播放音乐
|
||||
*/
|
||||
@JSONField(name = "hqmusicurl")
|
||||
@XStreamAlias("HQMusicUrl")
|
||||
@XmlElement(name = "HQMusicUrl")
|
||||
private String hqMusicUrl;
|
||||
/**
|
||||
* 缩略图的媒体id,通过上传多媒体文件,得到的id
|
||||
*/
|
||||
@JSONField(name = "thumb_media_id")
|
||||
@XStreamAlias("ThumbMediaId")
|
||||
@XmlElement(name = "ThumbMediaId")
|
||||
private String thumbMediaId;
|
||||
|
||||
public Music(String thumbMediaId) {
|
||||
|
||||
@@ -3,8 +3,10 @@ package com.foxinmy.weixin4j.tuple;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 图文对象
|
||||
@@ -18,7 +20,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XStreamAlias("Articles")
|
||||
@XmlRootElement(name = "Articles")
|
||||
public class News implements NotifyTuple {
|
||||
|
||||
private static final long serialVersionUID = 3348756809039388415L;
|
||||
@@ -36,7 +38,7 @@ public class News implements NotifyTuple {
|
||||
* @see com.foxinmy.weixin4j.tuple.Article
|
||||
*/
|
||||
@JSONField(name = "articles")
|
||||
@XStreamAlias("Articles")
|
||||
@XmlElement(name = "Articles")
|
||||
private List<Article> articles;
|
||||
|
||||
public News() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.foxinmy.weixin4j.tuple;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* 文本对象
|
||||
@@ -14,7 +14,7 @@ import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XStreamAlias("Content")
|
||||
@XmlRootElement(name = "Content")
|
||||
public class Text implements MassTuple, NotifyTuple {
|
||||
|
||||
private static final long serialVersionUID = 520050144519064503L;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.foxinmy.weixin4j.tuple;
|
||||
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
/**
|
||||
* 视频对象
|
||||
@@ -29,24 +30,24 @@ public class Video implements NotifyTuple {
|
||||
* 上传视频微信返回的媒体ID
|
||||
*/
|
||||
@JSONField(name = "media_id")
|
||||
@XStreamAlias("MediaId")
|
||||
@XmlElement(name = "MediaId")
|
||||
private String mediaId;
|
||||
/**
|
||||
* 缩略图的媒体ID(客服消息)
|
||||
*/
|
||||
@XStreamOmitField
|
||||
@JSONField(name = "thumb_media_id")
|
||||
@XmlTransient
|
||||
private String thumbMediaId;
|
||||
/**
|
||||
* 视频标题
|
||||
*/
|
||||
@XStreamAlias("Title")
|
||||
@XmlElement(name = "Title")
|
||||
private String title;
|
||||
/**
|
||||
* 视频描述
|
||||
*/
|
||||
@JSONField(name = "description")
|
||||
@XStreamAlias("Description")
|
||||
@XmlElement(name = "Description")
|
||||
private String desc;
|
||||
|
||||
public Video(String mediaId) {
|
||||
|
||||
@@ -51,6 +51,23 @@ public final class StringUtil {
|
||||
return !isBlank(cs);
|
||||
}
|
||||
|
||||
public static String uncapitalize(final String str) {
|
||||
int strLen;
|
||||
if (str == null || (strLen = str.length()) == 0) {
|
||||
return str;
|
||||
}
|
||||
|
||||
char firstChar = str.charAt(0);
|
||||
if (Character.isLowerCase(firstChar)) {
|
||||
// already uncapitalized
|
||||
return str;
|
||||
}
|
||||
|
||||
return new StringBuilder(strLen)
|
||||
.append(Character.toLowerCase(firstChar))
|
||||
.append(str.substring(1)).toString();
|
||||
}
|
||||
|
||||
public static String capitalize(final String str) {
|
||||
int strLen;
|
||||
if (str == null || (strLen = str.length()) == 0) {
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.foxinmy.weixin4j.xml;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAnyElement;
|
||||
|
||||
public class ListWrapper<T> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 7550802632983954221L;
|
||||
|
||||
private List<T> items;
|
||||
|
||||
public ListWrapper() {
|
||||
items = new ArrayList<T>();
|
||||
}
|
||||
|
||||
@XmlAnyElement(lax = true)
|
||||
public List<T> getItems() {
|
||||
return items;
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package com.foxinmy.weixin4j.xml;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.thoughtworks.xstream.converters.MarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.UnmarshallingContext;
|
||||
import com.thoughtworks.xstream.converters.collections.MapConverter;
|
||||
import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.mapper.Mapper;
|
||||
|
||||
/**
|
||||
* Map转换为实体对象
|
||||
*
|
||||
* @className Map2ObjectConverter
|
||||
* @author jy
|
||||
* @date 2015年3月29日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class Map2ObjectConverter extends MapConverter {
|
||||
|
||||
public Map2ObjectConverter(Mapper mapper) {
|
||||
super(mapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object unmarshal(HierarchicalStreamReader reader,
|
||||
UnmarshallingContext context) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
while (reader.hasMoreChildren()) {
|
||||
reader.moveDown();
|
||||
map.put(reader.getNodeName(), reader.getValue());
|
||||
reader.moveUp();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void marshal(Object source, HierarchicalStreamWriter writer,
|
||||
MarshallingContext context) {
|
||||
Map<?, ?> map = (Map<?, ?>) source;
|
||||
for (Entry<?, ?> entry : map.entrySet()) {
|
||||
if (entry.getValue() == null) {
|
||||
continue;
|
||||
}
|
||||
String value = entry.getValue().toString();
|
||||
if (StringUtil.isBlank(value)) {
|
||||
continue;
|
||||
}
|
||||
ExtendedHierarchicalStreamWriterHelper.startNode(writer, entry
|
||||
.getKey().toString(), entry.getClass());
|
||||
writer.setValue(value);
|
||||
writer.endNode();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
添加<![CDATA[]>支持
|
||||
@@ -1,30 +0,0 @@
|
||||
package com.foxinmy.weixin4j.xml;
|
||||
|
||||
import com.foxinmy.weixin4j.tuple.Text;
|
||||
import com.thoughtworks.xstream.converters.SingleValueConverter;
|
||||
|
||||
/**
|
||||
* Text回复消息转换
|
||||
*
|
||||
* @className TextConverter
|
||||
* @author jy
|
||||
* @date 2014年11月22日
|
||||
* @since JDK 1.7
|
||||
*/
|
||||
public class TextConverter implements SingleValueConverter {
|
||||
|
||||
@Override
|
||||
public boolean canConvert(@SuppressWarnings("rawtypes") Class clazz) {
|
||||
return clazz.equals(Text.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(Object obj) {
|
||||
return ((Text) obj).getContent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object fromString(String text) {
|
||||
return new Text(text);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +1,274 @@
|
||||
package com.foxinmy.weixin4j.xml;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
|
||||
import com.thoughtworks.xstream.core.util.QuickWriter;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamDriver;
|
||||
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
|
||||
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
|
||||
import com.thoughtworks.xstream.io.xml.Xpp3Driver;
|
||||
|
||||
public class XmlStream extends com.thoughtworks.xstream.XStream {
|
||||
|
||||
public XmlStream() {
|
||||
|
||||
super(new Xpp3Driver() {
|
||||
|
||||
@Override
|
||||
public HierarchicalStreamWriter createWriter(Writer out) {
|
||||
return new PrettyPrintWriter(out) {
|
||||
|
||||
@Override
|
||||
protected void writeText(QuickWriter writer, String text) {
|
||||
writer.write("<![CDATA[");
|
||||
writer.write(text);
|
||||
writer.write("]]>");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public XmlStream(HierarchicalStreamDriver hierarchicalStreamDriver) {
|
||||
super(hierarchicalStreamDriver);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromXML(String xml, Class<T> t) {
|
||||
return (T) super.fromXML(xml);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T fromXML(InputStream inputStream, Class<T> t) {
|
||||
return (T) super.fromXML(inputStream);
|
||||
}
|
||||
|
||||
public static XmlStream get() {
|
||||
XmlStream xstream = new XmlStream();
|
||||
xstream.ignoreUnknownElements();
|
||||
xstream.autodetectAnnotations(true);
|
||||
return xstream;
|
||||
}
|
||||
|
||||
public static <T> T get(InputStream inputStream, Class<T> clazz) {
|
||||
XmlStream xStream = get();
|
||||
xStream.alias("xml", clazz);
|
||||
xStream.processAnnotations(clazz);
|
||||
return xStream.fromXML(inputStream, clazz);
|
||||
}
|
||||
|
||||
public static <T> T get(String xml, Class<T> clazz) {
|
||||
XmlStream xStream = get();
|
||||
xStream.alias("xml", clazz);
|
||||
xStream.processAnnotations(clazz);
|
||||
return xStream.fromXML(xml, clazz);
|
||||
}
|
||||
|
||||
public static String to(Object obj) {
|
||||
XmlStream xStream = get();
|
||||
Class<?> clazz = obj.getClass();
|
||||
xStream.alias("xml", clazz);
|
||||
xStream.processAnnotations(clazz);
|
||||
return xStream.toXML(obj);
|
||||
}
|
||||
|
||||
public static void to(Object obj, OutputStream out) {
|
||||
XmlStream xStream = get();
|
||||
Class<?> clazz = obj.getClass();
|
||||
xStream.alias("xml", clazz);
|
||||
xStream.processAnnotations(clazz);
|
||||
xStream.toXML(obj, out);
|
||||
}
|
||||
}
|
||||
package com.foxinmy.weixin4j.xml;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.bind.JAXBContext;
|
||||
import javax.xml.bind.JAXBElement;
|
||||
import javax.xml.bind.JAXBException;
|
||||
import javax.xml.bind.Marshaller;
|
||||
import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.namespace.QName;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLOutputFactory;
|
||||
import javax.xml.stream.XMLStreamConstants;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.stream.XMLStreamWriter;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
|
||||
/**
|
||||
* XML 处理
|
||||
*
|
||||
* @className XmlStream
|
||||
* @author jy
|
||||
* @date 2015年6月2日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public final class XmlStream {
|
||||
private final static String ROOT_ELEMENT_XML = "xml";
|
||||
private final static String XML_VERSION = "1.0";
|
||||
private final static Map<Class<?>, Unmarshaller> messageUnmarshaller;
|
||||
private final static Map<Class<?>, Marshaller> messageMarshaller;
|
||||
static {
|
||||
messageUnmarshaller = new HashMap<Class<?>, Unmarshaller>();
|
||||
messageMarshaller = new HashMap<Class<?>, Marshaller>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml2Bean
|
||||
*
|
||||
* @param content
|
||||
* xml内容
|
||||
* @param clazz
|
||||
* bean类型
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T fromXML(InputStream content, Class<T> clazz) {
|
||||
Unmarshaller unmarshaller = messageUnmarshaller.get(clazz);
|
||||
if (unmarshaller == null) {
|
||||
try {
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
|
||||
unmarshaller = jaxbContext.createUnmarshaller();
|
||||
messageUnmarshaller.put(clazz, unmarshaller);
|
||||
} catch (JAXBException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
Source source = new StreamSource(content);
|
||||
XmlRootElement rootElement = clazz
|
||||
.getAnnotation(XmlRootElement.class);
|
||||
if (rootElement == null) {
|
||||
JAXBElement<T> jaxbElement = unmarshaller.unmarshal(source,
|
||||
clazz);
|
||||
return jaxbElement.getValue();
|
||||
} else {
|
||||
return (T) unmarshaller.unmarshal(source);
|
||||
}
|
||||
} catch (JAXBException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
} finally {
|
||||
if (content != null) {
|
||||
try {
|
||||
content.close();
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Xml2Bean
|
||||
*
|
||||
* @param content
|
||||
* xml内容
|
||||
* @param clazz
|
||||
* bean类型
|
||||
* @return
|
||||
*/
|
||||
public static <T> T fromXML(String content, Class<T> clazz) {
|
||||
return fromXML(
|
||||
new ByteArrayInputStream(content.getBytes(Consts.UTF_8)), clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* map2xml
|
||||
*
|
||||
* @param map
|
||||
* value无嵌套的map
|
||||
* @return xml内容
|
||||
*/
|
||||
public static String map2xml(Map<String, String> map) {
|
||||
StringWriter sw = new StringWriter();
|
||||
try {
|
||||
XMLStreamWriter xw = XMLOutputFactory.newInstance()
|
||||
.createXMLStreamWriter(sw);
|
||||
xw.writeStartDocument(Consts.UTF_8.name(), XML_VERSION);
|
||||
xw.writeStartElement(ROOT_ELEMENT_XML);
|
||||
for (Iterator<Entry<String, String>> it = map.entrySet().iterator(); it
|
||||
.hasNext();) {
|
||||
Entry<String, String> entry = it.next();
|
||||
xw.writeStartElement(entry.getKey());
|
||||
xw.writeCData(entry.getValue());
|
||||
xw.writeEndElement();
|
||||
}
|
||||
xw.writeEndDocument();
|
||||
xw.flush();
|
||||
xw.close();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
} finally {
|
||||
try {
|
||||
sw.close();
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
return sw.getBuffer().toString();
|
||||
}
|
||||
|
||||
public static String map2xml(JSONObject json) {
|
||||
StringWriter sw = new StringWriter();
|
||||
try {
|
||||
XMLStreamWriter xw = XMLOutputFactory.newInstance()
|
||||
.createXMLStreamWriter(sw);
|
||||
xw.writeStartDocument(Consts.UTF_8.name(), XML_VERSION);
|
||||
xw.writeStartElement(ROOT_ELEMENT_XML);
|
||||
Set<String> keys = json.keySet();
|
||||
for (String key : keys) {
|
||||
xw.writeStartElement(key);
|
||||
xw.writeCData(json.getString(key));
|
||||
xw.writeEndElement();
|
||||
}
|
||||
xw.writeEndDocument();
|
||||
xw.flush();
|
||||
xw.close();
|
||||
} catch (XMLStreamException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
} finally {
|
||||
try {
|
||||
sw.close();
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
return sw.getBuffer().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* xml2map
|
||||
*
|
||||
* @param content
|
||||
* 无嵌套节点的xml内容
|
||||
* @return map对象
|
||||
*/
|
||||
public static Map<String, String> xml2map(String content) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
StringReader sr = new StringReader(content);
|
||||
try {
|
||||
XMLStreamReader xr = XMLInputFactory.newInstance()
|
||||
.createXMLStreamReader(sr);
|
||||
while (true) {
|
||||
int event = xr.next();
|
||||
if (event == XMLStreamConstants.END_DOCUMENT) {
|
||||
xr.close();
|
||||
break;
|
||||
} else if (event == XMLStreamConstants.START_ELEMENT) {
|
||||
String name = xr.getLocalName();
|
||||
while (true) {
|
||||
event = xr.next();
|
||||
if (event == XMLStreamConstants.START_ELEMENT) {
|
||||
name = xr.getLocalName();
|
||||
} else if (event == XMLStreamConstants.END_ELEMENT) {
|
||||
break;
|
||||
} else if (event == XMLStreamConstants.CHARACTERS) {
|
||||
String value = xr.getText();
|
||||
map.put(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (XMLStreamException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
} finally {
|
||||
sr.close();
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean2Xml
|
||||
*
|
||||
* @param object
|
||||
* bean对象
|
||||
* @return xml内容
|
||||
*/
|
||||
public static String toXML(Object object) {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
toXML(object, os);
|
||||
return StringUtil.newStringUtf8(os.toByteArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* Bean2Xml
|
||||
*
|
||||
* @param t
|
||||
* bean对象
|
||||
* @param os
|
||||
* 输出流
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> void toXML(T t, OutputStream os) {
|
||||
Class<T> clazz = (Class<T>) t.getClass();
|
||||
Marshaller marshaller = messageMarshaller.get(clazz);
|
||||
if (marshaller == null) {
|
||||
try {
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
|
||||
marshaller = jaxbContext.createMarshaller();
|
||||
messageMarshaller.put(clazz, marshaller);
|
||||
} catch (JAXBException e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
XmlRootElement rootElement = clazz
|
||||
.getAnnotation(XmlRootElement.class);
|
||||
if (rootElement == null) {
|
||||
marshaller.marshal(new JAXBElement<T>(new QName(
|
||||
ROOT_ELEMENT_XML), clazz, t), os);
|
||||
} else {
|
||||
marshaller.marshal(t, os);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
} finally {
|
||||
if (os != null) {
|
||||
try {
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user