一般国内的攻城狮喜欢用tomcat进行调试自己的程序,但往往发布到生产环境就会 出现各种各样问题。
比如 上一篇文章我们谈了fastweixin最基本的使用,也许你在tomcat里面使用没有任何问题,但发布到weblogic上就会出现各种各样问题:
ExceptionPrecondition for readText is nextEvent().getTypeEventType() ==START_ELEMENT
查看fastweixin原始代码
可以看到其使用Javax里面xml解析器 而在Weblogic中,默认使用weblogic自己实现javax类,用这个处理xml 会出问题。
大家需要注意的是,javax开头的类,一般第三方容器很多都有自己实现,相同API的Class,默认一般都是自己实现Class,而不是使用JDK里面的。
我个人解决方法就是使用第三方jar,比如xmlpull替代。
下面是修改后的代码:
package com.fastwixinextend;
import com.github.sd4324530.fastweixin.util.CollectionUtil;
import com.github.sd4324530.fastweixin.util.StrUtil;
import com.github.sd4324530.fastweixin.util.StreamUtil;
import com.qq.weixin.mp.aes.AesException;
import com.qq.weixin.mp.aes.WXBizMsgCrypt;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
/**luozhuang
* ExceptionPrecondition for readText is nextEvent().getTypeEventType() ==
* START_ELEMENT 原始代码使用Javax里面xml解析器 在Weblogic中,默认使用weblogic自己实现的xml 会出问题
*/
public class MyMessageUtil {
public MyMessageUtil() {
super();
}
private static final Logger LOG
= LoggerFactory.getLogger(MyMessageUtil.class);
private static final String FORMAT
= "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>";
/**
* 解析从微信服务器来的请求,将消息或者事件返回出去
*
* @param request http请求对象
* @param token 用户设置的taken
* @param appId 公众号的APPID
* @param aesKey 用户设置的加密密钥
* @return 微信消息或者事件Map
*/
public static Map<String, Object> parseXml(HttpServletRequest request,
String token, String appId,
String aesKey) {
Map<String, Object> map = new HashMap<String, Object>();
InputStream inputStream = null;
String message = null;
try {
inputStream = request.getInputStream();
if (StrUtil.isNotBlank(aesKey)) {
ByteArrayOutputStream outputStream
= new ByteArrayOutputStream();
StreamUtil.copy(inputStream, outputStream);
String body = outputStream.toString("UTF-8");
LOG.debug("收到的消息密文:{}", body);
DocumentBuilderFactory dbf
= DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
StringReader sr = new StringReader(body);
InputSource is = new InputSource(sr);
Document document = db.parse(is);
Element root = document.getDocumentElement();
NodeList nodelist1 = root.getElementsByTagName("Encrypt");
WXBizMsgCrypt pc = new WXBizMsgCrypt(token, aesKey, appId);
String msgSignature = request.getParameter("msg_signature");
String timeStamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
LOG.debug("msgSignature:{}", msgSignature);
LOG.debug("timeStamp:{}", timeStamp);
LOG.debug("nonce:{}", nonce);
String encrypt = nodelist1.item(0).getTextContent();
String fromXML = String.format(FORMAT, encrypt);
message
= pc.DecryptMsg(msgSignature, timeStamp, nonce, fromXML);
LOG.debug("收到的消息:{}", message);
}
inputStream = new ByteArrayInputStream(message.getBytes("UTF-8"));
XmlPullParserFactory pullFactory
= XmlPullParserFactory.newInstance();
XmlPullParser reader = pullFactory.newPullParser();
// 设置输入流 并指明编码方式
reader.setInput(inputStream, "UTF-8");
// 产生第一个事件
int eventType = reader.getEventType();
// 只要不是文档结束事件,就一直循环
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
String tagName = reader.getName();
if ("SendPicsInfo".equals(tagName)) {
map.put(tagName, eventSendPicsInfo(reader));
} else if ("SendLocationInfo".equals(tagName)) {
map.put(tagName, eventSendLocationInfo(reader));
} else if ("ScanCodeInfo".equals(tagName)) {
map.put(tagName, eventScanCodePush(reader));
} else if ("xml".equals(tagName)) {
} else {
eventType = reader.next();
map.put(tagName, reader.getText());
}
}
eventType = reader.next();
}
} catch (IOException e) {
LOG.error("IO出现异常", e);
} catch (ParserConfigurationException e) {
LOG.error("XML解析出现异常", e);
} catch (SAXException e) {
LOG.error("XML解析出现异常", e);
} catch (AesException e) {
LOG.error("Aes异常", e);
} catch (XmlPullParserException e) {
LOG.error("XML解析出现异常", e);
} finally {
try {
if (inputStream != null) {
inputStream.close();
}
} catch (IOException e) {
}
}
return map;
}
/**
* Event为pic_sysphoto, pic_photo_or_album, pic_weixin时触发
*
* @param reader reader
* @return 读取结果
* @throws XMLStreamException XML解析异常
*/
protected static Map<String, Object> eventSendPicsInfo(XmlPullParser reader) throws XmlPullParserException,
IOException {
Map<String, Object> sendPicsInfoMap = new HashMap<String, Object>();
int eventType = reader.next();
while (eventType != XmlPullParser.END_DOCUMENT) {
eventType = reader.next();
if (eventType == XmlPullParser.START_TAG) {
String tagName = reader.getName();
if ("Count".equals(tagName)) {
eventType = reader.next();
sendPicsInfoMap.put(tagName, reader.getText());
} else if ("PicList".equals(tagName)) {
// StringBuilder sb = new StringBuilder();
List<Map<String, String>> picList
= CollectionUtil.newArrayList();
while (eventType != XmlPullParser.END_DOCUMENT) {
int event1 = reader.next();
if (event1 == XmlPullParser.START_TAG
&& "PicMd5Sum".equals(reader.getName())) {
Map<String, String> picMap
= new HashMap<String, String>();
eventType = reader.next();
picMap.put("PicMd5Sum", reader.getText());
// sb.append(reader.getText()());
// sb.append(",");
picList.add(picMap);
} else if (event1 == XmlPullParser.END_TAG
&& "PicList".equals(reader.getName())) {
break;
}
}
// sendPicsInfoMap.put(tagName, sb.substring(0, sb.length()));
sendPicsInfoMap.put(tagName, picList);
}
}
}
return sendPicsInfoMap;
}
/**
* Event为location_select时触发
*
* @param reader reader
* @return 读取结果
* @throws XMLStreamException XML解析异常
*/
protected static Map<String, Object> eventSendLocationInfo(XmlPullParser reader) throws XmlPullParserException,
IOException {
Map<String, Object> sendLocationInfo = new HashMap<String, Object>();
int eventType = reader.next();
while (eventType != XmlPullParser.END_DOCUMENT) {
eventType = reader.next();
if (eventType == XmlPullParser.START_TAG) {
String tagName = reader.getName().toString();
eventType = reader.next();
sendLocationInfo.put(tagName, reader.getText());
}
}
return sendLocationInfo;
}
/**
* Event为scancode_push, scancode_waitmsg时触发
*
* @param reader reader
* @return 读取结果
* @throws XMLStreamException XML解析异常
*/
protected static Map<String, Object> eventScanCodePush(XmlPullParser reader) throws XmlPullParserException,
IOException {
Map<String, Object> scanCodePush = new HashMap<String, Object>();
int eventType = reader.next();
while (eventType != XmlPullParser.END_DOCUMENT) {
eventType = reader.next();
if (eventType == XmlPullParser.START_TAG) {
String tagName = reader.getName();
eventType = reader.next();
scanCodePush.put(tagName, reader.getText());
}
}
return scanCodePush;
}
}