issue #71 替换掉JAXB,避免因OpenJDK造成无法deserialize xml的错误

This commit is contained in:
Daniel Qian 2015-01-19 15:12:14 +08:00
parent eaa77bc7b3
commit f3ec0b1965
73 changed files with 834 additions and 986 deletions

10
pom.xml
View File

@ -55,16 +55,6 @@
<artifactId>httpmime</artifactId> <artifactId>httpmime</artifactId>
<version>${httpclient.version}</version> <version>${httpclient.version}</version>
</dependency> </dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.7</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.7</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId> <artifactId>gson</artifactId>

View File

@ -14,6 +14,11 @@
<description>微信公众号、企业号Java SDK Common</description> <description>微信公众号、企业号Java SDK Common</description>
<dependencies> <dependencies>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.7</version>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>

View File

@ -1,24 +0,0 @@
package me.chanjar.weixin.common.util.xml;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/**
*
* http://stackoverflow.com/questions/14193944/jaxb-marshalling-unmarshalling-with-cdata
*
* @author Daniel Qian
*
*/
public class AdapterCDATA extends XmlAdapter<String, String> {
@Override
public String marshal(String arg0) throws Exception {
return "<![CDATA[" + arg0 + "]]>";
}
@Override
public String unmarshal(String arg0) throws Exception {
return arg0;
}
}

View File

@ -1,21 +0,0 @@
package me.chanjar.weixin.common.util.xml;
import javax.xml.bind.annotation.adapters.XmlAdapter;
/**
* @author Daniel Qian
*/
public class MediaIdMarshaller extends XmlAdapter<String, String> {
@Override
public String marshal(String arg0) throws Exception {
return "<MediaId><![CDATA[" + arg0 + "]]></MediaId>";
}
@Override
public String unmarshal(String arg0) throws Exception {
// do nothing
return arg0;
}
}

View File

@ -0,0 +1,15 @@
package me.chanjar.weixin.common.util.xml;
import com.thoughtworks.xstream.converters.basic.StringConverter;
/**
* Created by qianjia on 15/1/19.
*/
public class XStreamCDataConverter extends StringConverter {
@Override
public String toString(Object obj) {
return "<![CDATA[" + super.toString(obj) + "]]>";
}
}

View File

@ -0,0 +1,46 @@
package me.chanjar.weixin.common.util.xml;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.converters.basic.DoubleConverter;
import com.thoughtworks.xstream.converters.basic.FloatConverter;
import com.thoughtworks.xstream.converters.basic.IntConverter;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import java.io.Writer;
/**
* Created by qianjia on 15/1/19.
*/
public class XStreamInitializer {
public static XStream getInstance() {
XStream xstream = new XStream(new XppDriver() {
@Override
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out, getNameCoder()) {
protected String PREFIX_CDATA = "<![CDATA[";
protected String SUFFIX_CDATA = "]]>";
protected String PREFIX_MEDIA_ID = "<MediaId>";
protected String SUFFIX_MEDIA_ID = "</MediaId>";
@Override
protected void writeText(QuickWriter writer, String text) {
if (text.startsWith(PREFIX_CDATA) && text.endsWith(SUFFIX_CDATA)) {
writer.write(text);
} else if (text.startsWith(PREFIX_MEDIA_ID) && text.endsWith(SUFFIX_MEDIA_ID)) {
writer.write(text);
} else {
super.writeText(writer, text);
}
}
};
}
});
xstream.setMode(XStream.NO_REFERENCES);
return xstream;
}
}

View File

@ -0,0 +1,11 @@
package me.chanjar.weixin.common.util.xml;
/**
* Created by qianjia on 15/1/19.
*/
public class XStreamMediaIdConverter extends XStreamCDataConverter {
@Override
public String toString(Object obj) {
return "<MediaId>" + super.toString(obj) + "</MediaId>";
}
}

View File

@ -1,10 +1,10 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import java.util.Map;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage; import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
import java.util.Map;
/** /**
* 处理微信推送消息的处理器接口 * 处理微信推送消息的处理器接口
* @author Daniel Qian * @author Daniel Qian

View File

@ -1,9 +1,9 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import java.util.Map;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage; import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
import java.util.Map;
/** /**
* 微信消息拦截器可以用来做验证 * 微信消息拦截器可以用来做验证
* @author Daniel Qian * @author Daniel Qian

View File

@ -1,5 +1,8 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -8,9 +11,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
/** /**
* <pre> * <pre>
* 微信消息路由器通过代码化的配置把来自微信的消息交给handler处理 * 微信消息路由器通过代码化的配置把来自微信的消息交给handler处理

View File

@ -1,18 +1,19 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.bean.WxCpMessage;
import me.chanjar.weixin.cp.bean.WxCpTag;
import me.chanjar.weixin.cp.bean.WxCpUser;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.cp.bean.*;
import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.common.exception.WxErrorException;
/** /**
* 微信API的Service * 微信API的Service
*/ */

View File

@ -1,11 +1,11 @@
package me.chanjar.weixin.cp.bean; package me.chanjar.weixin.cp.bean;
import java.util.ArrayList;
import java.util.List;
import me.chanjar.weixin.cp.bean.messagebuilder.*; import me.chanjar.weixin.cp.bean.messagebuilder.*;
import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder; import me.chanjar.weixin.cp.util.json.WxCpGsonBuilder;
import java.util.ArrayList;
import java.util.List;
/** /**
* 消息 * 消息
* @author Daniel Qian * @author Daniel Qian

View File

@ -1,14 +1,13 @@
package me.chanjar.weixin.cp.bean; package me.chanjar.weixin.cp.bean;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.cp.api.WxCpConfigStorage; import me.chanjar.weixin.cp.api.WxCpConfigStorage;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import me.chanjar.weixin.cp.util.xml.XmlTransformer; import me.chanjar.weixin.cp.util.xml.XStreamTransformer;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
@ -25,103 +24,102 @@ import java.util.List;
* *
* @author Daniel Qian * @author Daniel Qian
*/ */
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxCpXmlMessage { public class WxCpXmlMessage {
/////////////////////// ///////////////////////
// 以下都是微信推送过来的消息的xml的element所对应的属性 // 以下都是微信推送过来的消息的xml的element所对应的属性
/////////////////////// ///////////////////////
@XmlElement(name="AgentID") @XStreamAlias("AgentID")
private Integer agentId; private Integer agentId;
@XmlElement(name = "ToUserName") @XStreamAlias("ToUserName")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String toUserName; private String toUserName;
@XmlElement(name = "FromUserName") @XStreamAlias("FromUserName")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String fromUserName; private String fromUserName;
@XmlElement(name = "CreateTime") @XStreamAlias("CreateTime")
private Long createTime; private Long createTime;
@XmlElement(name = "MsgType") @XStreamAlias("MsgType")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String msgType; private String msgType;
@XmlElement(name = "Content") @XStreamAlias("Content")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String content; private String content;
@XmlElement(name = "MsgId") @XStreamAlias("MsgId")
private Long msgId; private Long msgId;
@XmlElement(name = "PicUrl") @XStreamAlias("PicUrl")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String picUrl; private String picUrl;
@XmlElement(name = "MediaId") @XStreamAlias("MediaId")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String mediaId; private String mediaId;
@XmlElement(name = "Format") @XStreamAlias("Format")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String format; private String format;
@XmlElement(name = "ThumbMediaId") @XStreamAlias("ThumbMediaId")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String thumbMediaId; private String thumbMediaId;
@XmlElement(name = "Location_X") @XStreamAlias("Location_X")
private Double locationX; private Double locationX;
@XmlElement(name = "Location_Y") @XStreamAlias("Location_Y")
private Double locationY; private Double locationY;
@XmlElement(name = "Scale") @XStreamAlias("Scale")
private Double scale; private Double scale;
@XmlElement(name = "Label") @XStreamAlias("Label")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String label; private String label;
@XmlElement(name = "Title") @XStreamAlias("Title")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String title; private String title;
@XmlElement(name = "Description") @XStreamAlias("Description")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String description; private String description;
@XmlElement(name = "Url") @XStreamAlias("Url")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String url; private String url;
@XmlElement(name = "Event") @XStreamAlias("Event")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String event; private String event;
@XmlElement(name = "EventKey") @XStreamAlias("EventKey")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String eventKey; private String eventKey;
@XmlElement(name = "Ticket") @XStreamAlias("Ticket")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String ticket; private String ticket;
@XmlElement(name = "Latitude") @XStreamAlias("Latitude")
private Double latitude; private Double latitude;
@XmlElement(name = "Longitude") @XStreamAlias("Longitude")
private Double longitude; private Double longitude;
@XmlElement(name = "Precision") @XStreamAlias("Precision")
private Double precision; private Double precision;
@XmlElement(name = "Recognition") @XStreamAlias("Recognition")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String recognition; private String recognition;
/////////////////////////////////////// ///////////////////////////////////////
@ -130,37 +128,37 @@ public class WxCpXmlMessage {
/** /**
* 群发的结果 * 群发的结果
*/ */
@XmlElement(name = "Status") @XStreamAlias("Status")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String status; private String status;
/** /**
* group_id下粉丝数或者openid_list中的粉丝数 * group_id下粉丝数或者openid_list中的粉丝数
*/ */
@XmlElement(name = "TotalCount") @XStreamAlias("TotalCount")
private Integer totalCount; private Integer totalCount;
/** /**
* 过滤过滤是指特定地区性别的过滤用户设置拒收的过滤用户接收已超4条的过滤准备发送的粉丝数原则上filterCount = sentCount + errorCount * 过滤过滤是指特定地区性别的过滤用户设置拒收的过滤用户接收已超4条的过滤准备发送的粉丝数原则上filterCount = sentCount + errorCount
*/ */
@XmlElement(name = "FilterCount") @XStreamAlias("FilterCount")
private Integer filterCount; private Integer filterCount;
/** /**
* 发送成功的粉丝数 * 发送成功的粉丝数
*/ */
@XmlElement(name = "SentCount") @XStreamAlias("SentCount")
private Integer sentCount; private Integer sentCount;
/** /**
* 发送失败的粉丝数 * 发送失败的粉丝数
*/ */
@XmlElement(name = "ErrorCount") @XStreamAlias("ErrorCount")
private Integer errorCount; private Integer errorCount;
@XmlElement(name = "ScanCodeInfo") @XStreamAlias("ScanCodeInfo")
private ScanCodeInfo scanCodeInfo = new ScanCodeInfo(); private ScanCodeInfo scanCodeInfo = new ScanCodeInfo();
@XmlElement(name = "SendPicsInfo") @XStreamAlias("SendPicsInfo")
private SendPicsInfo sendPicsInfo = new SendPicsInfo(); private SendPicsInfo sendPicsInfo = new SendPicsInfo();
@XmlElement(name = "SendLocationInfo") @XStreamAlias("SendLocationInfo")
private SendLocationInfo sendLocationInfo = new SendLocationInfo(); private SendLocationInfo sendLocationInfo = new SendLocationInfo();
public Integer getAgentId() { public Integer getAgentId() {
@ -390,19 +388,11 @@ public class WxCpXmlMessage {
} }
protected static WxCpXmlMessage fromXml(String xml) { protected static WxCpXmlMessage fromXml(String xml) {
try { return XStreamTransformer.fromXml(WxCpXmlMessage.class, xml);
return XmlTransformer.fromXml(WxCpXmlMessage.class, xml);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
} }
protected static WxCpXmlMessage fromXml(InputStream is) { protected static WxCpXmlMessage fromXml(InputStream is) {
try { return XStreamTransformer.fromXml(WxCpXmlMessage.class, is);
return XmlTransformer.fromXml(WxCpXmlMessage.class, is);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
} }
/** /**
@ -499,16 +489,15 @@ public class WxCpXmlMessage {
this.sendLocationInfo = sendLocationInfo; this.sendLocationInfo = sendLocationInfo;
} }
@XmlRootElement(name = "ScanCodeInfo") @XStreamAlias("ScanCodeInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public static class ScanCodeInfo { public static class ScanCodeInfo {
@XmlElement(name = "ScanType") @XStreamAlias("ScanType")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String scanType; private String scanType;
@XmlElement(name = "ScanResult") @XStreamAlias("ScanResult")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String scanResult; private String scanResult;
/** /**
@ -538,15 +527,13 @@ public class WxCpXmlMessage {
} }
@XmlRootElement(name = "SendPicsInfo") @XStreamAlias("SendPicsInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public static class SendPicsInfo { public static class SendPicsInfo {
@XmlElement(name = "Count") @XStreamAlias("Count")
private Long count; private Long count;
@XmlElementWrapper(name="PicList") @XStreamAlias("PicList")
@XmlElement(name = "item")
protected final List<Item> picList = new ArrayList<Item>(); protected final List<Item> picList = new ArrayList<Item>();
public Long getCount() { public Long getCount() {
@ -561,13 +548,11 @@ public class WxCpXmlMessage {
return picList; return picList;
} }
@XmlRootElement(name = "item") @XStreamAlias("item")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "WxXmlMessage.SendPicsInfo.Item")
public static class Item { public static class Item {
@XmlElement(name = "PicMd5Sum") @XStreamAlias("PicMd5Sum")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String PicMd5Sum; private String PicMd5Sum;
public String getPicMd5Sum() { public String getPicMd5Sum() {
@ -580,28 +565,27 @@ public class WxCpXmlMessage {
} }
} }
@XmlRootElement(name = "SendLocationInfo") @XStreamAlias("SendLocationInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public static class SendLocationInfo { public static class SendLocationInfo {
@XmlElement(name = "Location_X") @XStreamAlias("Location_X")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String locationX; private String locationX;
@XmlElement(name = "Location_Y") @XStreamAlias("Location_Y")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String locationY; private String locationY;
@XmlElement(name = "Scale") @XStreamAlias("Scale")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String scale; private String scale;
@XmlElement(name = "Label") @XStreamAlias("Label")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String label; private String label;
@XmlElement(name = "Poiname") @XStreamAlias("Poiname")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String poiname; private String poiname;
public String getLocationX() { public String getLocationX() {

View File

@ -1,20 +1,15 @@
package me.chanjar.weixin.cp.bean; package me.chanjar.weixin.cp.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.MediaIdMarshaller; import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter;
import javax.xml.bind.annotation.XmlAccessType; @XStreamAlias("xml")
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxCpXmlOutImageMessage extends WxCpXmlOutMessage { public class WxCpXmlOutImageMessage extends WxCpXmlOutMessage {
@XmlElement(name="Image") @XStreamAlias("Image")
@XmlJavaTypeAdapter(MediaIdMarshaller.class) @XStreamConverter(value=XStreamMediaIdConverter.class)
private String mediaId; private String mediaId;
public WxCpXmlOutImageMessage() { public WxCpXmlOutImageMessage() {

View File

@ -1,35 +1,29 @@
package me.chanjar.weixin.cp.bean; package me.chanjar.weixin.cp.bean;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.cp.api.WxCpConfigStorage; import me.chanjar.weixin.cp.api.WxCpConfigStorage;
import me.chanjar.weixin.cp.bean.outxmlbuilder.*; import me.chanjar.weixin.cp.bean.outxmlbuilder.*;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import me.chanjar.weixin.cp.util.xml.XmlTransformer; import me.chanjar.weixin.cp.util.xml.XStreamTransformer;
import javax.xml.bind.JAXBException; @XStreamAlias("xml")
import javax.xml.bind.annotation.XmlAccessType; public abstract class WxCpXmlOutMessage {
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "xml") @XStreamAlias("ToUserName")
@XmlAccessorType(XmlAccessType.FIELD) @XStreamConverter(value=XStreamCDataConverter.class)
public class WxCpXmlOutMessage {
@XmlElement(name="ToUserName")
@XmlJavaTypeAdapter(AdapterCDATA.class)
protected String toUserName; protected String toUserName;
@XmlElement(name="FromUserName") @XStreamAlias("FromUserName")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
protected String fromUserName; protected String fromUserName;
@XmlElement(name="CreateTime") @XStreamAlias("CreateTime")
protected Long createTime; protected Long createTime;
@XmlElement(name="MsgType") @XStreamAlias("MsgType")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
protected String msgType; protected String msgType;
public String getToUserName() { public String getToUserName() {
@ -65,11 +59,7 @@ public class WxCpXmlOutMessage {
} }
protected String toXml() { protected String toXml() {
try { return XStreamTransformer.toXml((Class)this.getClass(), this);
return XmlTransformer.toXml((Class)this.getClass(), this);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
} }
/** /**

View File

@ -1,22 +1,20 @@
package me.chanjar.weixin.cp.bean; package me.chanjar.weixin.cp.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage { public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage {
@XmlElement(name = "ArticleCount") @XStreamAlias("ArticleCount")
protected int articleCount; protected int articleCount;
@XmlElementWrapper(name="Articles") @XStreamAlias("Articles")
@XmlElement(name = "item")
protected final List<Item> articles = new ArrayList<Item>(); protected final List<Item> articles = new ArrayList<Item>();
public WxCpXmlOutNewsMessage() { public WxCpXmlOutNewsMessage() {
@ -37,24 +35,23 @@ public class WxCpXmlOutNewsMessage extends WxCpXmlOutMessage {
} }
@XmlRootElement(name = "Item") @XStreamAlias("item")
@XmlAccessorType(XmlAccessType.FIELD)
public static class Item { public static class Item {
@XmlElement(name = "Title") @XStreamAlias("Title")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String Title; private String Title;
@XmlElement(name = "Description") @XStreamAlias("Description")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String Description; private String Description;
@XmlElement(name="PicUrl") @XStreamAlias("PicUrl")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String PicUrl; private String PicUrl;
@XmlElement(name="Url") @XStreamAlias("Url")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String Url; private String Url;
public String getTitle() { public String getTitle() {

View File

@ -1,20 +1,15 @@
package me.chanjar.weixin.cp.bean; package me.chanjar.weixin.cp.bean;
import javax.xml.bind.annotation.XmlAccessType; import com.thoughtworks.xstream.annotations.XStreamAlias;
import javax.xml.bind.annotation.XmlAccessorType; import com.thoughtworks.xstream.annotations.XStreamConverter;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxCpXmlOutTextMessage extends WxCpXmlOutMessage { public class WxCpXmlOutTextMessage extends WxCpXmlOutMessage {
@XmlElement(name="Content") @XStreamAlias("Content")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String content; private String content;
public WxCpXmlOutTextMessage() { public WxCpXmlOutTextMessage() {

View File

@ -1,19 +1,14 @@
package me.chanjar.weixin.cp.bean; package me.chanjar.weixin.cp.bean;
import javax.xml.bind.annotation.XmlAccessType; import com.thoughtworks.xstream.annotations.XStreamAlias;
import javax.xml.bind.annotation.XmlAccessorType; import com.thoughtworks.xstream.annotations.XStreamConverter;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage { public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage {
@XmlElement(name = "Video") @XStreamAlias("Video")
protected final Video video = new Video(); protected final Video video = new Video();
public WxCpXmlOutVideoMessage() { public WxCpXmlOutVideoMessage() {
@ -45,20 +40,19 @@ public class WxCpXmlOutVideoMessage extends WxCpXmlOutMessage {
} }
@XmlRootElement(name = "Video") @XStreamAlias("Video")
@XmlAccessorType(XmlAccessType.FIELD) public static class Video {
private static class Video {
@XmlElement(name = "MediaId") @XStreamAlias("MediaId")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String mediaId; private String mediaId;
@XmlElement(name = "Title") @XStreamAlias("Title")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String title; private String title;
@XmlElement(name = "Description") @XStreamAlias("Description")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String description; private String description;
public String getMediaId() { public String getMediaId() {

View File

@ -1,20 +1,15 @@
package me.chanjar.weixin.cp.bean; package me.chanjar.weixin.cp.bean;
import javax.xml.bind.annotation.XmlAccessType; import com.thoughtworks.xstream.annotations.XStreamAlias;
import javax.xml.bind.annotation.XmlAccessorType; import com.thoughtworks.xstream.annotations.XStreamConverter;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.MediaIdMarshaller; import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter;
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxCpXmlOutVoiceMessage extends WxCpXmlOutMessage { public class WxCpXmlOutVoiceMessage extends WxCpXmlOutMessage {
@XmlElement(name="Voice") @XStreamAlias("Voice")
@XmlJavaTypeAdapter(MediaIdMarshaller.class) @XStreamConverter(value=XStreamMediaIdConverter.class)
private String mediaId; private String mediaId;
public WxCpXmlOutVoiceMessage() { public WxCpXmlOutVoiceMessage() {

View File

@ -1,11 +1,11 @@
package me.chanjar.weixin.cp.bean.outxmlbuilder; package me.chanjar.weixin.cp.bean.outxmlbuilder;
import java.util.ArrayList;
import java.util.List;
import me.chanjar.weixin.cp.bean.WxCpXmlOutNewsMessage; import me.chanjar.weixin.cp.bean.WxCpXmlOutNewsMessage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutNewsMessage.Item; import me.chanjar.weixin.cp.bean.WxCpXmlOutNewsMessage.Item;
import java.util.ArrayList;
import java.util.List;
/** /**
* 图文消息builder * 图文消息builder
* @author Daniel Qian * @author Daniel Qian

View File

@ -8,18 +8,11 @@
*/ */
package me.chanjar.weixin.cp.util.json; package me.chanjar.weixin.cp.util.json;
import java.lang.reflect.Type; import com.google.gson.*;
import me.chanjar.weixin.common.util.json.GsonHelper; import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.cp.bean.WxCpDepart; import me.chanjar.weixin.cp.bean.WxCpDepart;
import com.google.gson.JsonDeserializationContext; import java.lang.reflect.Type;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
/** /**
* @author Daniel Qian * @author Daniel Qian

View File

@ -2,11 +2,12 @@ package me.chanjar.weixin.cp.util.json;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.util.json.WxMediaUploadResultAdapter;
import me.chanjar.weixin.common.util.json.WxErrorAdapter; import me.chanjar.weixin.common.util.json.WxErrorAdapter;
import me.chanjar.weixin.cp.bean.*; import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.bean.WxCpMessage;
import me.chanjar.weixin.cp.bean.WxCpTag;
import me.chanjar.weixin.cp.bean.WxCpUser;
public class WxCpGsonBuilder { public class WxCpGsonBuilder {

View File

@ -8,12 +8,12 @@
*/ */
package me.chanjar.weixin.cp.util.json; package me.chanjar.weixin.cp.util.json;
import java.lang.reflect.Type;
import com.google.gson.*; import com.google.gson.*;
import me.chanjar.weixin.common.util.json.GsonHelper; import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.cp.bean.WxCpUser; import me.chanjar.weixin.cp.bean.WxCpUser;
import java.lang.reflect.Type;
/** /**
* @author Daniel Qian * @author Daniel Qian
*/ */

View File

@ -0,0 +1,106 @@
package me.chanjar.weixin.cp.util.xml;
import com.thoughtworks.xstream.XStream;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.cp.bean.*;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* Created by qianjia on 15/1/19.
*/
public class XStreamTransformer {
protected static final Map<Class, XStream> CLASS_2_XSTREAM_INSTANCE = configXStreamInstance();
/**
* xml -> pojo
*
* @param clazz
* @param xml
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, String xml) {
T object = (T) CLASS_2_XSTREAM_INSTANCE.get(clazz).fromXML(xml);
return object;
}
@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, InputStream is) {
T object = (T) CLASS_2_XSTREAM_INSTANCE.get(clazz).fromXML(is);
return object;
}
/**
* pojo -> xml
*
* @param clazz
* @param object
* @return
*/
public static <T> String toXml(Class<T> clazz, T object) {
return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object);
}
private static Map<Class, XStream> configXStreamInstance() {
Map<Class, XStream> map = new HashMap<Class, XStream>();
map.put(WxCpXmlMessage.class, config_WxCpXmlMessage());
map.put(WxCpXmlOutNewsMessage.class, config_WxCpXmlOutNewsMessage());
map.put(WxCpXmlOutTextMessage.class, config_WxCpXmlOutTextMessage());
map.put(WxCpXmlOutImageMessage.class, config_WxCpXmlOutImageMessage());
map.put(WxCpXmlOutVideoMessage.class, config_WxCpXmlOutVideoMessage());
map.put(WxCpXmlOutVoiceMessage.class, config_WxCpXmlOutVoiceMessage());
return map;
}
private static XStream config_WxCpXmlMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxCpXmlMessage.class);
xstream.processAnnotations(WxCpXmlMessage.ScanCodeInfo.class);
xstream.processAnnotations(WxCpXmlMessage.SendPicsInfo.class);
xstream.processAnnotations(WxCpXmlMessage.SendPicsInfo.Item.class);
xstream.processAnnotations(WxCpXmlMessage.SendLocationInfo.class);
return xstream;
}
private static XStream config_WxCpXmlOutImageMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutImageMessage.class);
return xstream;
}
private static XStream config_WxCpXmlOutNewsMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutNewsMessage.class);
xstream.processAnnotations(WxCpXmlOutNewsMessage.Item.class);
return xstream;
}
private static XStream config_WxCpXmlOutTextMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutTextMessage.class);
return xstream;
}
private static XStream config_WxCpXmlOutVideoMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutVideoMessage.class);
xstream.processAnnotations(WxCpXmlOutVideoMessage.Video.class);
return xstream;
}
private static XStream config_WxCpXmlOutVoiceMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxCpXmlOutMessage.class);
xstream.processAnnotations(WxCpXmlOutVoiceMessage.class);
return xstream;
}
}

View File

@ -1,93 +0,0 @@
package me.chanjar.weixin.cp.util.xml;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import javax.xml.bind.*;
import me.chanjar.weixin.cp.bean.*;
import org.xml.sax.InputSource;
import com.sun.xml.bind.marshaller.CharacterEscapeHandler;
public class XmlTransformer {
protected static final JAXBContext JAXB_CONTEXT = initJAXBContext();
/**
* xml -> pojo
*
* @param clazz
* @param xml
* @return
* @throws JAXBException
*/
@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, String xml) throws JAXBException {
Unmarshaller um = JAXB_CONTEXT.createUnmarshaller();
T object = (T) um.unmarshal(new StringReader(xml));
return object;
}
@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, InputStream is) throws JAXBException {
Unmarshaller um = JAXB_CONTEXT.createUnmarshaller();
InputSource inputSource = new InputSource(is);
inputSource.setEncoding("utf-8");
T object = (T) um.unmarshal(inputSource);
return object;
}
/**
* pojo -> xml
*
* @param clazz
* @param object
* @return
* @throws JAXBException
*/
public static <T> String toXml(Class<T> clazz, T object) throws JAXBException {
StringWriter stringWriter = new StringWriter();
toXml(clazz, object, stringWriter);
return stringWriter.getBuffer().toString();
}
public static <T> void toXml(Class<T> clazz, T object, Writer writer) throws JAXBException {
Marshaller m = JAXB_CONTEXT.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.setProperty(CharacterEscapeHandler.class.getName(), CHAR_ESCAPE_HANDLER);
m.setProperty(Marshaller.JAXB_FRAGMENT, true);
m.marshal(object, writer);
}
protected static final CharacterEscapeHandler CHAR_ESCAPE_HANDLER = new CharacterUnescapeHandler();
protected static class CharacterUnescapeHandler implements CharacterEscapeHandler {
public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException {
writer.write(ac, i, j);
}
}
private static JAXBContext initJAXBContext() {
/*
* JAXBContext对象是线程安全的根据官方文档的建议将对象作为全局实例
* https://jaxb.java.net/guide/Performance_and_thread_safety.html
*/
try {
return JAXBContext.newInstance(
WxCpXmlOutMessage.class,
WxCpXmlOutImageMessage.class,
WxCpXmlOutNewsMessage.class,
WxCpXmlOutTextMessage.class,
WxCpXmlOutVideoMessage.class,
WxCpXmlOutVoiceMessage.class,
WxCpXmlMessage.class);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,23 +1,17 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import java.io.InputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import com.google.inject.Binder; import com.google.inject.Binder;
import com.google.inject.Module; import com.google.inject.Module;
import org.xml.sax.InputSource; import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import java.io.InputStream;
public class ApiTestModule implements Module { public class ApiTestModule implements Module {
@Override @Override
public void configure(Binder binder) { public void configure(Binder binder) {
try {
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
WxXmlCpInMemoryConfigStorage config = fromXml(WxXmlCpInMemoryConfigStorage.class, is1); WxXmlCpInMemoryConfigStorage config = fromXml(WxXmlCpInMemoryConfigStorage.class, is1);
WxCpServiceImpl wxService = new WxCpServiceImpl(); WxCpServiceImpl wxService = new WxCpServiceImpl();
@ -25,21 +19,16 @@ public class ApiTestModule implements Module {
binder.bind(WxCpServiceImpl.class).toInstance(wxService); binder.bind(WxCpServiceImpl.class).toInstance(wxService);
binder.bind(WxCpConfigStorage.class).toInstance(config); binder.bind(WxCpConfigStorage.class).toInstance(config);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
} }
public static <T> T fromXml(Class<T> clazz, InputStream is) throws JAXBException { public static <T> T fromXml(Class<T> clazz, InputStream is) {
Unmarshaller um = JAXBContext.newInstance(clazz).createUnmarshaller(); XStream xstream = XStreamInitializer.getInstance();
InputSource inputSource = new InputSource(is); xstream.alias("xml", clazz);
inputSource.setEncoding("utf-8"); xstream.processAnnotations(clazz);
T object = (T) um.unmarshal(inputSource); return (T) xstream.fromXML(is);
return object;
} }
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
public static class WxXmlCpInMemoryConfigStorage extends WxCpInMemoryConfigStorage { public static class WxXmlCpInMemoryConfigStorage extends WxCpInMemoryConfigStorage {
protected String userId; protected String userId;

View File

@ -1,14 +1,12 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.StringUtils; import me.chanjar.weixin.common.util.StringUtils;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException;
import com.google.inject.Inject;
/** /**
* 基础API测试 * 基础API测试
* @author Daniel Qian * @author Daniel Qian

View File

@ -1,15 +1,13 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import java.util.List; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpDepart; import me.chanjar.weixin.cp.bean.WxCpDepart;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException; import java.util.List;
import com.google.inject.Inject;
/** /**
* 测试部门接口 * 测试部门接口

View File

@ -1,20 +1,18 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import java.io.IOException; import com.google.inject.Inject;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException; import java.io.IOException;
import java.io.InputStream;
import com.google.inject.Inject; import java.util.ArrayList;
import java.util.List;
/** /**
* 测试多媒体文件上传下载 * 测试多媒体文件上传下载

View File

@ -1,14 +1,12 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpMessage; import me.chanjar.weixin.cp.bean.WxCpMessage;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException;
import com.google.inject.Inject;
/*** /***
* 测试发送消息 * 测试发送消息
* @author Daniel Qian * @author Daniel Qian

View File

@ -1,7 +1,5 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import java.util.Map;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage; import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
@ -9,6 +7,8 @@ import org.testng.Assert;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.Map;
/** /**
* 测试消息路由器 * 测试消息路由器
* @author Daniel Qian * @author Daniel Qian

View File

@ -1,9 +1,9 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import com.google.inject.Inject; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.cp.bean.WxCpDepart; import me.chanjar.weixin.cp.bean.WxCpDepart;
import me.chanjar.weixin.cp.bean.WxCpUser; import me.chanjar.weixin.cp.bean.WxCpUser;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;

View File

@ -1,19 +1,15 @@
package me.chanjar.weixin.cp.api; package me.chanjar.weixin.cp.api;
import javax.xml.bind.JAXBException; import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxMenu; import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Inject;
import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton;
import me.chanjar.weixin.common.exception.WxErrorException;
/** /**
* 测试菜单 * 测试菜单
* @author Daniel Qian * @author Daniel Qian
@ -42,7 +38,7 @@ public class WxMenuAPITest {
} }
@DataProvider(name="menu") @DataProvider(name="menu")
public Object[][] getMenu() throws JAXBException { public Object[][] getMenu() {
WxMenu menu = new WxMenu(); WxMenu menu = new WxMenu();
WxMenuButton button1 = new WxMenuButton(); WxMenuButton button1 = new WxMenuButton();
button1.setType(WxConsts.BUTTON_CLICK); button1.setType(WxConsts.BUTTON_CLICK);

View File

@ -1,11 +1,10 @@
package me.chanjar.weixin.cp.bean; package me.chanjar.weixin.cp.bean;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.cp.bean.WxCpMessage.WxArticle;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.cp.bean.WxCpMessage.WxArticle;
@Test @Test
public class WxCpMessageTest { public class WxCpMessageTest {

View File

@ -1,21 +1,16 @@
package me.chanjar.weixin.cp.demo; package me.chanjar.weixin.cp.demo;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.cp.api.WxCpInMemoryConfigStorage; import me.chanjar.weixin.cp.api.WxCpInMemoryConfigStorage;
import org.xml.sax.InputSource;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.InputStream; import java.io.InputStream;
/** /**
* @author Daniel Qian * @author Daniel Qian
*/ */
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
class WxCpDemoInMemoryConfigStorage extends WxCpInMemoryConfigStorage { class WxCpDemoInMemoryConfigStorage extends WxCpInMemoryConfigStorage {
@Override @Override
@ -25,11 +20,10 @@ class WxCpDemoInMemoryConfigStorage extends WxCpInMemoryConfigStorage {
} }
public static WxCpDemoInMemoryConfigStorage fromXml(InputStream is) throws JAXBException { public static WxCpDemoInMemoryConfigStorage fromXml(InputStream is) {
Unmarshaller um = JAXBContext.newInstance(WxCpDemoInMemoryConfigStorage.class).createUnmarshaller(); XStream xstream = XStreamInitializer.getInstance();
InputSource inputSource = new InputSource(is); xstream.processAnnotations(WxCpDemoInMemoryConfigStorage.class);
inputSource.setEncoding("utf-8"); return (WxCpDemoInMemoryConfigStorage) xstream.fromXML(is);
return (WxCpDemoInMemoryConfigStorage) um.unmarshal(inputSource);
} }
} }

View File

@ -8,7 +8,6 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler; import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder; import org.eclipse.jetty.servlet.ServletHolder;
import javax.xml.bind.JAXBException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Map; import java.util.Map;
@ -37,7 +36,6 @@ public class WxCpDemoServer {
} }
private static void initWeixin() { private static void initWeixin() {
try {
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(is1); WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(is1);
@ -87,8 +85,5 @@ public class WxCpDemoServer {
.end() .end()
; ;
} catch (JAXBException e) {
throw new RuntimeException(e);
}
} }
} }

View File

@ -1,20 +1,18 @@
package me.chanjar.weixin.cp.demo; package me.chanjar.weixin.cp.demo;
import me.chanjar.weixin.common.util.StringUtils; import me.chanjar.weixin.common.util.StringUtils;
import me.chanjar.weixin.cp.api.*; import me.chanjar.weixin.cp.api.WxCpConfigStorage;
import me.chanjar.weixin.cp.api.WxCpMessageRouter;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpXmlMessage; import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage; import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
import me.chanjar.weixin.cp.bean.WxCpXmlOutTextMessage;
import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil; import me.chanjar.weixin.cp.util.crypto.WxCpCryptUtil;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
/** /**
* @author Daniel Qian * @author Daniel Qian

View File

@ -2,10 +2,10 @@ package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.bean.WxMenu; import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.mp.bean.*; import me.chanjar.weixin.mp.bean.*;
import me.chanjar.weixin.mp.bean.result.*; import me.chanjar.weixin.mp.bean.result.*;
import me.chanjar.weixin.common.exception.WxErrorException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;

View File

@ -1,32 +0,0 @@
package me.chanjar.weixin.mp.bean;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.MediaIdMarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxMpMpXmlOutImageMessage extends WxMpXmlOutMessage {
@XmlElement(name="Image")
@XmlJavaTypeAdapter(MediaIdMarshaller.class)
private String mediaId;
public WxMpMpXmlOutImageMessage() {
this.msgType = WxConsts.XML_MSG_IMAGE;
}
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
}

View File

@ -1,14 +1,13 @@
package me.chanjar.weixin.mp.bean; package me.chanjar.weixin.mp.bean;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil; import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil;
import me.chanjar.weixin.mp.util.xml.XmlTransformer; import me.chanjar.weixin.mp.util.xml.XStreamTransformer;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
@ -25,100 +24,99 @@ import java.util.List;
* *
* @author chanjarster * @author chanjarster
*/ */
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxMpXmlMessage { public class WxMpXmlMessage {
/////////////////////// ///////////////////////
// 以下都是微信推送过来的消息的xml的element所对应的属性 // 以下都是微信推送过来的消息的xml的element所对应的属性
/////////////////////// ///////////////////////
@XmlElement(name = "ToUserName") @XStreamAlias("ToUserName")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String toUserName; private String toUserName;
@XmlElement(name = "FromUserName") @XStreamAlias("FromUserName")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String fromUserName; private String fromUserName;
@XmlElement(name = "CreateTime") @XStreamAlias("CreateTime")
private Long createTime; private Long createTime;
@XmlElement(name = "MsgType") @XStreamAlias("MsgType")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String msgType; private String msgType;
@XmlElement(name = "Content") @XStreamAlias("Content")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String content; private String content;
@XmlElement(name = "MsgId") @XStreamAlias("MsgId")
private Long msgId; private Long msgId;
@XmlElement(name = "PicUrl") @XStreamAlias("PicUrl")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String picUrl; private String picUrl;
@XmlElement(name = "MediaId") @XStreamAlias("MediaId")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String mediaId; private String mediaId;
@XmlElement(name = "Format") @XStreamAlias("Format")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String format; private String format;
@XmlElement(name = "ThumbMediaId") @XStreamAlias("ThumbMediaId")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String thumbMediaId; private String thumbMediaId;
@XmlElement(name = "Location_X") @XStreamAlias("Location_X")
private Double locationX; private Double locationX;
@XmlElement(name = "Location_Y") @XStreamAlias("Location_Y")
private Double locationY; private Double locationY;
@XmlElement(name = "Scale") @XStreamAlias("Scale")
private Double scale; private Double scale;
@XmlElement(name = "Label") @XStreamAlias("Label")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String label; private String label;
@XmlElement(name = "Title") @XStreamAlias("Title")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String title; private String title;
@XmlElement(name = "Description") @XStreamAlias("Description")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String description; private String description;
@XmlElement(name = "Url") @XStreamAlias("Url")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String url; private String url;
@XmlElement(name = "Event") @XStreamAlias("Event")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String event; private String event;
@XmlElement(name = "EventKey") @XStreamAlias("EventKey")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String eventKey; private String eventKey;
@XmlElement(name = "Ticket") @XStreamAlias("Ticket")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String ticket; private String ticket;
@XmlElement(name = "Latitude") @XStreamAlias("Latitude")
private Double latitude; private Double latitude;
@XmlElement(name = "Longitude") @XStreamAlias("Longitude")
private Double longitude; private Double longitude;
@XmlElement(name = "Precision") @XStreamAlias("Precision")
private Double precision; private Double precision;
@XmlElement(name = "Recognition") @XStreamAlias("Recognition")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String recognition; private String recognition;
/////////////////////////////////////// ///////////////////////////////////////
@ -127,37 +125,37 @@ public class WxMpXmlMessage {
/** /**
* 群发的结果 * 群发的结果
*/ */
@XmlElement(name = "Status") @XStreamAlias("Status")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String status; private String status;
/** /**
* group_id下粉丝数或者openid_list中的粉丝数 * group_id下粉丝数或者openid_list中的粉丝数
*/ */
@XmlElement(name = "TotalCount") @XStreamAlias("TotalCount")
private Integer totalCount; private Integer totalCount;
/** /**
* 过滤过滤是指特定地区性别的过滤用户设置拒收的过滤用户接收已超4条的过滤准备发送的粉丝数原则上filterCount = sentCount + errorCount * 过滤过滤是指特定地区性别的过滤用户设置拒收的过滤用户接收已超4条的过滤准备发送的粉丝数原则上filterCount = sentCount + errorCount
*/ */
@XmlElement(name = "FilterCount") @XStreamAlias("FilterCount")
private Integer filterCount; private Integer filterCount;
/** /**
* 发送成功的粉丝数 * 发送成功的粉丝数
*/ */
@XmlElement(name = "SentCount") @XStreamAlias("SentCount")
private Integer sentCount; private Integer sentCount;
/** /**
* 发送失败的粉丝数 * 发送失败的粉丝数
*/ */
@XmlElement(name = "ErrorCount") @XStreamAlias("ErrorCount")
private Integer errorCount; private Integer errorCount;
@XmlElement(name = "ScanCodeInfo") @XStreamAlias("ScanCodeInfo")
private ScanCodeInfo scanCodeInfo = new ScanCodeInfo(); private ScanCodeInfo scanCodeInfo = new ScanCodeInfo();
@XmlElement(name = "SendPicsInfo") @XStreamAlias("SendPicsInfo")
private SendPicsInfo sendPicsInfo = new SendPicsInfo(); private SendPicsInfo sendPicsInfo = new SendPicsInfo();
@XmlElement(name = "SendLocationInfo") @XStreamAlias("SendLocationInfo")
private SendLocationInfo sendLocationInfo = new SendLocationInfo(); private SendLocationInfo sendLocationInfo = new SendLocationInfo();
public String getToUserName() { public String getToUserName() {
@ -380,21 +378,11 @@ public class WxMpXmlMessage {
} }
public static WxMpXmlMessage fromXml(String xml) { public static WxMpXmlMessage fromXml(String xml) {
try { return XStreamTransformer.fromXml(WxMpXmlMessage.class, xml);
// 操蛋的微信模板消息推送成功的消息是MsgID其他消息推送过来是MsgId
xml = xml.replaceAll("<MsgID>", "<MsgId>").replaceAll("</MsgID>", "</MsgId>");
return XmlTransformer.fromXml(WxMpXmlMessage.class, xml);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
} }
public static WxMpXmlMessage fromXml(InputStream is) { public static WxMpXmlMessage fromXml(InputStream is) {
try { return XStreamTransformer.fromXml(WxMpXmlMessage.class, is);
return fromXml(IOUtils.toString(is, "UTF-8"));
} catch (IOException e) {
throw new RuntimeException(e);
}
} }
/** /**
@ -491,16 +479,15 @@ public class WxMpXmlMessage {
this.sendLocationInfo = sendLocationInfo; this.sendLocationInfo = sendLocationInfo;
} }
@XmlRootElement(name = "ScanCodeInfo") @XStreamAlias("ScanCodeInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public static class ScanCodeInfo { public static class ScanCodeInfo {
@XmlElement(name = "ScanType") @XStreamAlias("ScanType")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String scanType; private String scanType;
@XmlElement(name = "ScanResult") @XStreamAlias("ScanResult")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String scanResult; private String scanResult;
/** /**
@ -530,15 +517,13 @@ public class WxMpXmlMessage {
} }
@XmlRootElement(name = "SendPicsInfo") @XStreamAlias("SendPicsInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public static class SendPicsInfo { public static class SendPicsInfo {
@XmlElement(name = "Count") @XStreamAlias("Count")
private Long count; private Long count;
@XmlElementWrapper(name="PicList") @XStreamAlias("PicList")
@XmlElement(name = "item")
protected final List<Item> picList = new ArrayList<Item>(); protected final List<Item> picList = new ArrayList<Item>();
public Long getCount() { public Long getCount() {
@ -553,47 +538,44 @@ public class WxMpXmlMessage {
return picList; return picList;
} }
@XmlRootElement(name = "item") @XStreamAlias("item")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "WxXmlMessage.SendPicsInfo.Item")
public static class Item { public static class Item {
@XmlElement(name = "PicMd5Sum") @XStreamAlias("PicMd5Sum")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String PicMd5Sum; private String picMd5Sum;
public String getPicMd5Sum() { public String getPicMd5Sum() {
return PicMd5Sum; return picMd5Sum;
} }
public void setPicMd5Sum(String picMd5Sum) { public void setPicMd5Sum(String picMd5Sum) {
PicMd5Sum = picMd5Sum; this.picMd5Sum = picMd5Sum;
} }
} }
} }
@XmlRootElement(name = "SendLocationInfo") @XStreamAlias("SendLocationInfo")
@XmlAccessorType(XmlAccessType.FIELD)
public static class SendLocationInfo { public static class SendLocationInfo {
@XmlElement(name = "Location_X") @XStreamAlias("Location_X")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String locationX; private String locationX;
@XmlElement(name = "Location_Y") @XStreamAlias("Location_Y")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String locationY; private String locationY;
@XmlElement(name = "Scale") @XStreamAlias("Scale")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String scale; private String scale;
@XmlElement(name = "Label") @XStreamAlias("Label")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String label; private String label;
@XmlElement(name = "Poiname") @XStreamAlias("Poiname")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String poiname; private String poiname;
public String getLocationX() { public String getLocationX() {

View File

@ -0,0 +1,27 @@
package me.chanjar.weixin.mp.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter;
@XStreamAlias("xml")
public class WxMpXmlOutImageMessage extends WxMpXmlOutMessage {
@XStreamAlias("Image")
@XStreamConverter(value = XStreamMediaIdConverter.class)
private String mediaId;
public String getMediaId() {
return mediaId;
}
public void setMediaId(String mediaId) {
this.mediaId = mediaId;
}
public WxMpXmlOutImageMessage() {
this.msgType = WxConsts.XML_MSG_IMAGE;
}
}

View File

@ -1,35 +1,29 @@
package me.chanjar.weixin.mp.bean; package me.chanjar.weixin.mp.bean;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.mp.api.WxMpConfigStorage; import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.bean.outxmlbuilder.*; import me.chanjar.weixin.mp.bean.outxmlbuilder.*;
import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil; import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil;
import me.chanjar.weixin.mp.util.xml.XmlTransformer; import me.chanjar.weixin.mp.util.xml.XStreamTransformer;
import javax.xml.bind.JAXBException; @XStreamAlias("xml")
import javax.xml.bind.annotation.XmlAccessType; public abstract class WxMpXmlOutMessage {
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "xml") @XStreamAlias("ToUserName")
@XmlAccessorType(XmlAccessType.FIELD) @XStreamConverter(value=XStreamCDataConverter.class)
public class WxMpXmlOutMessage {
@XmlElement(name="ToUserName")
@XmlJavaTypeAdapter(AdapterCDATA.class)
protected String toUserName; protected String toUserName;
@XmlElement(name="FromUserName") @XStreamAlias("FromUserName")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
protected String fromUserName; protected String fromUserName;
@XmlElement(name="CreateTime") @XStreamAlias("CreateTime")
protected Long createTime; protected Long createTime;
@XmlElement(name="MsgType") @XStreamAlias("MsgType")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
protected String msgType; protected String msgType;
public String getToUserName() { public String getToUserName() {
@ -65,11 +59,7 @@ public class WxMpXmlOutMessage {
} }
public String toXml() { public String toXml() {
try { return XStreamTransformer.toXml((Class) this.getClass(), this);
return XmlTransformer.toXml((Class)this.getClass(), this);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
} }
/** /**

View File

@ -1,19 +1,14 @@
package me.chanjar.weixin.mp.bean; package me.chanjar.weixin.mp.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import javax.xml.bind.annotation.XmlAccessType; @XStreamAlias("xml")
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage { public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage {
@XmlElement(name = "Music") @XStreamAlias("Music")
protected final Music music = new Music(); protected final Music music = new Music();
public WxMpXmlOutMusicMessage() { public WxMpXmlOutMusicMessage() {
@ -60,28 +55,27 @@ public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage {
music.setHqMusicUrl(hqMusicUrl); music.setHqMusicUrl(hqMusicUrl);
} }
@XmlRootElement(name = "Music") @XStreamAlias("Music")
@XmlAccessorType(XmlAccessType.FIELD) public static class Music {
private static class Music {
@XmlElement(name = "Title") @XStreamAlias("Title")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String title; private String title;
@XmlElement(name = "Description") @XStreamAlias("Description")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String description; private String description;
@XmlElement(name="ThumbMediaId") @XStreamAlias("ThumbMediaId")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String thumbMediaId; private String thumbMediaId;
@XmlElement(name="MusicUrl") @XStreamAlias("MusicUrl")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String musicUrl; private String musicUrl;
@XmlElement(name="HQMusicUrl") @XStreamAlias("HQMusicUrl")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String hqMusicUrl; private String hqMusicUrl;
public String getTitle() { public String getTitle() {

View File

@ -1,22 +1,20 @@
package me.chanjar.weixin.mp.bean; package me.chanjar.weixin.mp.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage { public class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage {
@XmlElement(name = "ArticleCount") @XStreamAlias("ArticleCount")
protected int articleCount; protected int articleCount;
@XmlElementWrapper(name="Articles") @XStreamAlias("Articles")
@XmlElement(name = "item")
protected final List<Item> articles = new ArrayList<Item>(); protected final List<Item> articles = new ArrayList<Item>();
public WxMpXmlOutNewsMessage() { public WxMpXmlOutNewsMessage() {
@ -37,24 +35,23 @@ public class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage {
} }
@XmlRootElement(name = "Item") @XStreamAlias("item")
@XmlAccessorType(XmlAccessType.FIELD)
public static class Item { public static class Item {
@XmlElement(name = "Title") @XStreamAlias("Title")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String Title; private String Title;
@XmlElement(name = "Description") @XStreamAlias("Description")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String Description; private String Description;
@XmlElement(name="PicUrl") @XStreamAlias("PicUrl")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String PicUrl; private String PicUrl;
@XmlElement(name="Url") @XStreamAlias("Url")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String Url; private String Url;
public String getTitle() { public String getTitle() {

View File

@ -1,20 +1,15 @@
package me.chanjar.weixin.mp.bean; package me.chanjar.weixin.mp.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import javax.xml.bind.annotation.XmlAccessType; @XStreamAlias("xml")
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxMpXmlOutTextMessage extends WxMpXmlOutMessage { public class WxMpXmlOutTextMessage extends WxMpXmlOutMessage {
@XmlElement(name="Content") @XStreamAlias("Content")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String content; private String content;
public WxMpXmlOutTextMessage() { public WxMpXmlOutTextMessage() {

View File

@ -1,19 +1,14 @@
package me.chanjar.weixin.mp.bean; package me.chanjar.weixin.mp.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.AdapterCDATA; import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import javax.xml.bind.annotation.XmlAccessType; @XStreamAlias("xml")
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage { public class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage {
@XmlElement(name = "Video") @XStreamAlias("Video")
protected final Video video = new Video(); protected final Video video = new Video();
public WxMpXmlOutVideoMessage() { public WxMpXmlOutVideoMessage() {
@ -45,20 +40,19 @@ public class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage {
} }
@XmlRootElement(name = "Video") @XStreamAlias("Video")
@XmlAccessorType(XmlAccessType.FIELD) public static class Video {
private static class Video {
@XmlElement(name = "MediaId") @XStreamAlias("MediaId")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String mediaId; private String mediaId;
@XmlElement(name = "Title") @XStreamAlias("Title")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String title; private String title;
@XmlElement(name = "Description") @XStreamAlias("Description")
@XmlJavaTypeAdapter(AdapterCDATA.class) @XStreamConverter(value=XStreamCDataConverter.class)
private String description; private String description;
public String getMediaId() { public String getMediaId() {

View File

@ -1,20 +1,15 @@
package me.chanjar.weixin.mp.bean; package me.chanjar.weixin.mp.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.util.xml.MediaIdMarshaller; import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter;
import javax.xml.bind.annotation.XmlAccessType; @XStreamAlias("xml")
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WxMpXmlOutVoiceMessage extends WxMpXmlOutMessage { public class WxMpXmlOutVoiceMessage extends WxMpXmlOutMessage {
@XmlElement(name="Voice") @XStreamAlias("Voice")
@XmlJavaTypeAdapter(MediaIdMarshaller.class) @XStreamConverter(value = XStreamMediaIdConverter.class)
private String mediaId; private String mediaId;
public WxMpXmlOutVoiceMessage() { public WxMpXmlOutVoiceMessage() {

View File

@ -1,12 +1,12 @@
package me.chanjar.weixin.mp.bean.outxmlbuilder; package me.chanjar.weixin.mp.bean.outxmlbuilder;
import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage; import me.chanjar.weixin.mp.bean.WxMpXmlOutImageMessage;
/** /**
* 图片消息builder * 图片消息builder
* @author chanjarster * @author chanjarster
*/ */
public final class ImageBuilder extends BaseBuilder<ImageBuilder, WxMpMpXmlOutImageMessage> { public final class ImageBuilder extends BaseBuilder<ImageBuilder, WxMpXmlOutImageMessage> {
private String mediaId; private String mediaId;
@ -15,8 +15,8 @@ public final class ImageBuilder extends BaseBuilder<ImageBuilder, WxMpMpXmlOutIm
return this; return this;
} }
public WxMpMpXmlOutImageMessage build() { public WxMpXmlOutImageMessage build() {
WxMpMpXmlOutImageMessage m = new WxMpMpXmlOutImageMessage(); WxMpXmlOutImageMessage m = new WxMpXmlOutImageMessage();
setCommon(m); setCommon(m);
m.setMediaId(this.mediaId); m.setMediaId(this.mediaId);
return m; return m;

View File

@ -1,6 +1,5 @@
package me.chanjar.weixin.mp.bean.result; package me.chanjar.weixin.mp.bean.result;
import me.chanjar.weixin.common.util.json.WxGsonBuilder;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
/** /**

View File

@ -1,12 +1,12 @@
package me.chanjar.weixin.mp.util.http; package me.chanjar.weixin.mp.util.http;
import me.chanjar.weixin.common.bean.result.WxError; import me.chanjar.weixin.common.bean.result.WxError;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.fs.FileUtils; import me.chanjar.weixin.common.util.fs.FileUtils;
import me.chanjar.weixin.common.util.http.InputStreamResponseHandler; import me.chanjar.weixin.common.util.http.InputStreamResponseHandler;
import me.chanjar.weixin.common.util.http.RequestExecutor; import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.Utf8ResponseHandler; import me.chanjar.weixin.common.util.http.Utf8ResponseHandler;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.apache.http.Header; import org.apache.http.Header;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ClientProtocolException;

View File

@ -4,7 +4,6 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import me.chanjar.weixin.mp.bean.*; import me.chanjar.weixin.mp.bean.*;
import me.chanjar.weixin.mp.bean.result.*; import me.chanjar.weixin.mp.bean.result.*;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
public class WxMpGsonBuilder { public class WxMpGsonBuilder {

View File

@ -1,7 +1,6 @@
package me.chanjar.weixin.mp.util.json; package me.chanjar.weixin.mp.util.json;
import com.google.gson.*; import com.google.gson.*;
import me.chanjar.weixin.common.bean.WxAccessToken;
import me.chanjar.weixin.common.util.json.GsonHelper; import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;

View File

@ -10,8 +10,6 @@ package me.chanjar.weixin.mp.util.json;
import com.google.gson.*; import com.google.gson.*;
import me.chanjar.weixin.common.util.json.GsonHelper; import me.chanjar.weixin.common.util.json.GsonHelper;
import me.chanjar.weixin.mp.bean.result.WxMpMassSendResult;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult; import me.chanjar.weixin.mp.bean.result.WxMpSemanticQueryResult;
import java.lang.reflect.Type; import java.lang.reflect.Type;

View File

@ -8,9 +8,10 @@
*/ */
package me.chanjar.weixin.mp.util.json; package me.chanjar.weixin.mp.util.json;
import com.google.gson.*; import com.google.gson.JsonElement;
import me.chanjar.weixin.common.api.WxConsts; import com.google.gson.JsonObject;
import me.chanjar.weixin.mp.bean.WxMpCustomMessage; import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import me.chanjar.weixin.mp.bean.WxMpTemplateData; import me.chanjar.weixin.mp.bean.WxMpTemplateData;
import me.chanjar.weixin.mp.bean.WxMpTemplateMessage; import me.chanjar.weixin.mp.bean.WxMpTemplateMessage;

View File

@ -0,0 +1,117 @@
package me.chanjar.weixin.mp.util.xml;
import com.thoughtworks.xstream.XStream;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.bean.*;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
/**
* Created by qianjia on 15/1/19.
*/
public class XStreamTransformer {
protected static final Map<Class, XStream> CLASS_2_XSTREAM_INSTANCE = configXStreamInstance();
/**
* xml -> pojo
*
* @param clazz
* @param xml
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, String xml) {
T object = (T) CLASS_2_XSTREAM_INSTANCE.get(clazz).fromXML(xml);
return object;
}
@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, InputStream is) {
T object = (T) CLASS_2_XSTREAM_INSTANCE.get(clazz).fromXML(is);
return object;
}
/**
* pojo -> xml
*
* @param clazz
* @param object
* @return
*/
public static <T> String toXml(Class<T> clazz, T object) {
return CLASS_2_XSTREAM_INSTANCE.get(clazz).toXML(object);
}
private static Map<Class, XStream> configXStreamInstance() {
Map<Class, XStream> map = new HashMap<Class, XStream>();
map.put(WxMpXmlMessage.class, config_WxMpXmlMessage());
map.put(WxMpXmlOutMusicMessage.class, config_WxMpXmlOutMusicMessage());
map.put(WxMpXmlOutNewsMessage.class, config_WxMpXmlOutNewsMessage());
map.put(WxMpXmlOutTextMessage.class, config_WxMpXmlOutTextMessage());
map.put(WxMpXmlOutImageMessage.class, config_WxMpXmlOutImageMessage());
map.put(WxMpXmlOutVideoMessage.class, config_WxMpXmlOutVideoMessage());
map.put(WxMpXmlOutVoiceMessage.class, config_WxMpXmlOutVoiceMessage());
return map;
}
private static XStream config_WxMpXmlMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpXmlMessage.class);
xstream.processAnnotations(WxMpXmlMessage.ScanCodeInfo.class);
xstream.processAnnotations(WxMpXmlMessage.SendPicsInfo.class);
xstream.processAnnotations(WxMpXmlMessage.SendPicsInfo.Item.class);
xstream.processAnnotations(WxMpXmlMessage.SendLocationInfo.class);
xstream.aliasField("MsgID", WxMpXmlMessage.class, "msgId");
return xstream;
}
private static XStream config_WxMpXmlOutImageMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpXmlOutMessage.class);
xstream.processAnnotations(WxMpXmlOutImageMessage.class);
return xstream;
}
private static XStream config_WxMpXmlOutNewsMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpXmlOutMessage.class);
xstream.processAnnotations(WxMpXmlOutNewsMessage.class);
xstream.processAnnotations(WxMpXmlOutNewsMessage.Item.class);
return xstream;
}
private static XStream config_WxMpXmlOutMusicMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpXmlOutMessage.class);
xstream.processAnnotations(WxMpXmlOutMusicMessage.class);
xstream.processAnnotations(WxMpXmlOutMusicMessage.Music.class);
return xstream;
}
private static XStream config_WxMpXmlOutTextMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpXmlOutMessage.class);
xstream.processAnnotations(WxMpXmlOutTextMessage.class);
return xstream;
}
private static XStream config_WxMpXmlOutVideoMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpXmlOutMessage.class);
xstream.processAnnotations(WxMpXmlOutVideoMessage.class);
xstream.processAnnotations(WxMpXmlOutVideoMessage.Video.class);
return xstream;
}
private static XStream config_WxMpXmlOutVoiceMessage() {
XStream xstream = XStreamInitializer.getInstance();
xstream.processAnnotations(WxMpXmlOutMessage.class);
xstream.processAnnotations(WxMpXmlOutVoiceMessage.class);
return xstream;
}
}

View File

@ -1,91 +0,0 @@
package me.chanjar.weixin.mp.util.xml;
import com.sun.xml.bind.marshaller.CharacterEscapeHandler;
import me.chanjar.weixin.mp.bean.*;
import org.xml.sax.InputSource;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.*;
public class XmlTransformer {
protected static final JAXBContext JAXB_CONTEXT = initJAXBContext();
/**
* xml -> pojo
*
* @param clazz
* @param xml
* @return
* @throws JAXBException
*/
@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, String xml) throws JAXBException {
Unmarshaller um = JAXB_CONTEXT.createUnmarshaller();
T object = (T) um.unmarshal(new StringReader(xml));
return object;
}
@SuppressWarnings("unchecked")
public static <T> T fromXml(Class<T> clazz, InputStream is) throws JAXBException {
Unmarshaller um = JAXB_CONTEXT.createUnmarshaller();
InputSource inputSource = new InputSource(is);
inputSource.setEncoding("utf-8");
T object = (T) um.unmarshal(inputSource);
return object;
}
/**
* pojo -> xml
*
* @param clazz
* @param object
* @return
* @throws JAXBException
*/
public static <T> String toXml(Class<T> clazz, T object) throws JAXBException {
StringWriter stringWriter = new StringWriter();
toXml(clazz, object, stringWriter);
return stringWriter.getBuffer().toString();
}
public static <T> void toXml(Class<T> clazz, T object, Writer writer) throws JAXBException {
Marshaller m = JAXB_CONTEXT.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.setProperty(CharacterEscapeHandler.class.getName(), CHAR_ESCAPE_HANDLER);
m.setProperty(Marshaller.JAXB_FRAGMENT, true);
m.marshal(object, writer);
}
protected static final CharacterEscapeHandler CHAR_ESCAPE_HANDLER = new CharacterUnescapeHandler();
protected static class CharacterUnescapeHandler implements CharacterEscapeHandler {
public void escape(char[] ac, int i, int j, boolean flag, Writer writer) throws IOException {
writer.write(ac, i, j);
}
}
private static JAXBContext initJAXBContext() {
/*
* JAXBContext对象是线程安全的根据官方文档的建议将对象作为全局实例
* https://jaxb.java.net/guide/Performance_and_thread_safety.html
*/
try {
return JAXBContext.newInstance(
WxMpXmlOutMessage.class,
WxMpMpXmlOutImageMessage.class,
WxMpXmlOutNewsMessage.class,
WxMpXmlOutMusicMessage.class,
WxMpXmlOutTextMessage.class,
WxMpXmlOutVideoMessage.class,
WxMpXmlOutVoiceMessage.class,
WxMpXmlMessage.class);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,23 +1,17 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import java.io.InputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import com.google.inject.Binder; import com.google.inject.Binder;
import com.google.inject.Module; import com.google.inject.Module;
import org.xml.sax.InputSource; import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import java.io.InputStream;
public class ApiTestModule implements Module { public class ApiTestModule implements Module {
@Override @Override
public void configure(Binder binder) { public void configure(Binder binder) {
try {
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
WxXmlMpInMemoryConfigStorage config = fromXml(WxXmlMpInMemoryConfigStorage.class, is1); WxXmlMpInMemoryConfigStorage config = fromXml(WxXmlMpInMemoryConfigStorage.class, is1);
WxMpServiceImpl wxService = new WxMpServiceImpl(); WxMpServiceImpl wxService = new WxMpServiceImpl();
@ -25,21 +19,16 @@ public class ApiTestModule implements Module {
binder.bind(WxMpServiceImpl.class).toInstance(wxService); binder.bind(WxMpServiceImpl.class).toInstance(wxService);
binder.bind(WxMpConfigStorage.class).toInstance(config); binder.bind(WxMpConfigStorage.class).toInstance(config);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
} }
public static <T> T fromXml(Class<T> clazz, InputStream is) throws JAXBException { public static <T> T fromXml(Class<T> clazz, InputStream is) {
Unmarshaller um = JAXBContext.newInstance(clazz).createUnmarshaller(); XStream xstream = XStreamInitializer.getInstance();
InputSource inputSource = new InputSource(is); xstream.alias("xml", clazz);
inputSource.setEncoding("utf-8"); xstream.processAnnotations(clazz);
T object = (T) um.unmarshal(inputSource); return (T) xstream.fromXML(is);
return object;
} }
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
public static class WxXmlMpInMemoryConfigStorage extends WxMpInMemoryConfigStorage { public static class WxXmlMpInMemoryConfigStorage extends WxMpInMemoryConfigStorage {
protected String openId; protected String openId;

View File

@ -1,14 +1,12 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.StringUtils; import me.chanjar.weixin.common.util.StringUtils;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException;
import com.google.inject.Inject;
/** /**
* 基础API测试 * 基础API测试
* @author chanjarster * @author chanjarster

View File

@ -1,14 +1,12 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.WxMpCustomMessage; import me.chanjar.weixin.mp.bean.WxMpCustomMessage;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException;
import com.google.inject.Inject;
/*** /***
* 测试发送客服消息 * 测试发送客服消息
* @author chanjarster * @author chanjarster

View File

@ -1,15 +1,13 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import java.util.List; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.WxMpGroup; import me.chanjar.weixin.mp.bean.WxMpGroup;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException; import java.util.List;
import com.google.inject.Inject;
/** /**
* 测试分组接口 * 测试分组接口

View File

@ -1,10 +1,9 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import java.io.IOException; import com.google.inject.Inject;
import java.io.InputStream;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage; import me.chanjar.weixin.mp.bean.WxMpMassGroupMessage;
import me.chanjar.weixin.mp.bean.WxMpMassNews; import me.chanjar.weixin.mp.bean.WxMpMassNews;
import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage;
@ -16,9 +15,8 @@ import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException; import java.io.IOException;
import java.io.InputStream;
import com.google.inject.Inject;
/** /**
* 测试群发消息 * 测试群发消息

View File

@ -1,20 +1,18 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import java.io.IOException; import com.google.inject.Inject;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException; import java.io.IOException;
import java.io.InputStream;
import com.google.inject.Inject; import java.util.ArrayList;
import java.util.List;
/** /**
* 测试多媒体文件上传下载 * 测试多媒体文件上传下载

View File

@ -1,19 +1,15 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import javax.xml.bind.JAXBException; import com.google.inject.Inject;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.inject.Inject;
import me.chanjar.weixin.common.bean.WxMenu;
import me.chanjar.weixin.common.bean.WxMenu.WxMenuButton;
import me.chanjar.weixin.common.exception.WxErrorException;
/** /**
* 测试菜单 * 测试菜单
* @author chanjarster * @author chanjarster
@ -42,7 +38,7 @@ public class WxMpMenuAPITest {
} }
@DataProvider(name="menu") @DataProvider(name="menu")
public Object[][] getMenu() throws JAXBException { public Object[][] getMenu() {
WxMenu menu = new WxMenu(); WxMenu menu = new WxMenu();
WxMenuButton button1 = new WxMenuButton(); WxMenuButton button1 = new WxMenuButton();
button1.setType(WxConsts.BUTTON_CLICK); button1.setType(WxConsts.BUTTON_CLICK);

View File

@ -1,7 +1,5 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import java.util.Map;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
@ -9,6 +7,8 @@ import org.testng.Assert;
import org.testng.annotations.DataProvider; import org.testng.annotations.DataProvider;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import java.util.Map;
/** /**
* 测试消息路由器 * 测试消息路由器
* @author chanjarster * @author chanjarster

View File

@ -1,15 +1,13 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import java.io.File; import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket; import me.chanjar.weixin.mp.bean.result.WxMpQrCodeTicket;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException; import java.io.File;
import com.google.inject.Inject;
/** /**
* 测试用户相关的接口 * 测试用户相关的接口

View File

@ -1,13 +1,11 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.common.exception.WxErrorException;
import com.google.inject.Inject;
/** /**
* 测试短连接 * 测试短连接
* *

View File

@ -1,15 +1,13 @@
package me.chanjar.weixin.mp.api; package me.chanjar.weixin.mp.api;
import com.google.inject.Inject;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.bean.result.WxMpUserList; import me.chanjar.weixin.mp.bean.result.WxMpUserList;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Guice; import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.common.exception.WxErrorException;
import com.google.inject.Inject;
/** /**
* 测试用户相关的接口 * 测试用户相关的接口
* @author chanjarster * @author chanjarster

View File

@ -1,11 +1,10 @@
package me.chanjar.weixin.mp.bean; package me.chanjar.weixin.mp.bean;
import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.WxMpCustomMessage.WxArticle;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import me.chanjar.weixin.mp.bean.WxMpCustomMessage.WxArticle;
@Test @Test
public class WxMpCustomMessageTest { public class WxMpCustomMessageTest {

View File

@ -7,7 +7,7 @@ import org.testng.annotations.Test;
public class WxMpXmlOutImageMessageTest { public class WxMpXmlOutImageMessageTest {
public void test() { public void test() {
WxMpMpXmlOutImageMessage m = new WxMpMpXmlOutImageMessage(); WxMpXmlOutImageMessage m = new WxMpXmlOutImageMessage();
m.setMediaId("ddfefesfsdfef"); m.setMediaId("ddfefesfsdfef");
m.setCreateTime(1122l); m.setCreateTime(1122l);
m.setFromUserName("from"); m.setFromUserName("from");
@ -25,7 +25,7 @@ public class WxMpXmlOutImageMessageTest {
} }
public void testBuild() { public void testBuild() {
WxMpMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build(); WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build();
String expected = "<xml>" String expected = "<xml>"
+ "<ToUserName><![CDATA[to]]></ToUserName>" + "<ToUserName><![CDATA[to]]></ToUserName>"
+ "<FromUserName><![CDATA[from]]></FromUserName>" + "<FromUserName><![CDATA[from]]></FromUserName>"

View File

@ -1,21 +1,16 @@
package me.chanjar.weixin.mp.demo; package me.chanjar.weixin.mp.demo;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import me.chanjar.weixin.common.util.xml.XStreamInitializer;
import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage; import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;
import org.xml.sax.InputSource;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.InputStream; import java.io.InputStream;
/** /**
* @author Daniel Qian * @author Daniel Qian
*/ */
@XmlRootElement(name = "xml") @XStreamAlias("xml")
@XmlAccessorType(XmlAccessType.FIELD)
class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage { class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage {
@Override @Override
@ -25,11 +20,10 @@ class WxMpDemoInMemoryConfigStorage extends WxMpInMemoryConfigStorage {
} }
public static WxMpDemoInMemoryConfigStorage fromXml(InputStream is) throws JAXBException { public static WxMpDemoInMemoryConfigStorage fromXml(InputStream is) {
Unmarshaller um = JAXBContext.newInstance(WxMpDemoInMemoryConfigStorage.class).createUnmarshaller(); XStream xstream = XStreamInitializer.getInstance();
InputSource inputSource = new InputSource(is); xstream.processAnnotations(WxMpDemoInMemoryConfigStorage.class);
inputSource.setEncoding("utf-8"); return (WxMpDemoInMemoryConfigStorage) xstream.fromXML(is);
return (WxMpDemoInMemoryConfigStorage) um.unmarshal(inputSource);
} }
} }

View File

@ -4,14 +4,14 @@ import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.*; import me.chanjar.weixin.mp.api.*;
import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutImageMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage; import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;
import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.*; import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import javax.xml.bind.JAXBException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Map; import java.util.Map;
@ -41,7 +41,6 @@ public class WxMpDemoServer {
} }
private static void initWeixin() { private static void initWeixin() {
try {
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml"); InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
WxMpDemoInMemoryConfigStorage config = WxMpDemoInMemoryConfigStorage.fromXml(is1); WxMpDemoInMemoryConfigStorage config = WxMpDemoInMemoryConfigStorage.fromXml(is1);
@ -67,7 +66,7 @@ public class WxMpDemoServer {
try { try {
WxMediaUploadResult wxMediaUploadResult = wxMpService WxMediaUploadResult wxMediaUploadResult = wxMpService
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg")); .mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
WxMpMpXmlOutImageMessage m WxMpXmlOutImageMessage m
= WxMpXmlOutMessage = WxMpXmlOutMessage
.IMAGE() .IMAGE()
.mediaId(wxMediaUploadResult.getMediaId()) .mediaId(wxMediaUploadResult.getMediaId())
@ -117,8 +116,5 @@ public class WxMpDemoServer {
.end() .end()
; ;
} catch (JAXBException e) {
throw new RuntimeException(e);
}
} }
} }

View File

@ -1,23 +1,17 @@
package me.chanjar.weixin.mp.demo; package me.chanjar.weixin.mp.demo;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.StringUtils; import me.chanjar.weixin.common.util.StringUtils;
import me.chanjar.weixin.mp.api.*; import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage; import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage; import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
/** /**
* @author Daniel Qian * @author Daniel Qian

View File

@ -1,26 +1,15 @@
package me.chanjar.weixin.mp.demo; package me.chanjar.weixin.mp.demo;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.util.StringUtils; import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.*;
import me.chanjar.weixin.mp.bean.WxMpMpXmlOutImageMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;
import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken; import me.chanjar.weixin.mp.bean.result.WxMpOAuth2AccessToken;
import me.chanjar.weixin.mp.bean.result.WxMpUser; import me.chanjar.weixin.mp.bean.result.WxMpUser;
import javax.servlet.ServletContext;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.JAXBException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
public class WxMpOAuth2Servlet extends HttpServlet { public class WxMpOAuth2Servlet extends HttpServlet {