您的位置:首页 > 移动开发 > 微信开发

微信----简单自动回复功能emoji和文本处理demo

2017-08-03 17:42 661 查看
概述:emoji和文本混在一起该怎么解析?做过微信都知道,不能直接判断发过是文本还是其他事件?必须要解析出来,但是解析成字符串之后,你会发现emoji会产生异常,或者显示不出来,因为emoji都是\开头字符串代表emoji,但是在解析成字符串,无论你用utf-8都不可以满足要求。

你会想读取两遍,但InputStream不允许重复读,是否存在可以重复的流,把它缓存起来,ByteArrayOutputStream就可以重复读。

<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[你好]]></Content>
</xml>



日志:

<?xml version="1.0" encoding="utf-8"?><xml> <ToUserName><![CDATA[33dfdfd]]></ToUserName> <FromUserName><![CDATA[3333-T_hZDR-YRjY]]></FromUserName> <CreateTime>1501751512</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[類峕]></Content>
<MsgId>6449973631174700350</MsgId> <Encrypt><![ddfd]]></Encrypt></xml>

这个emoji最后把右号解析没了

首先整个缓存类:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* 缓存InputStream,以便InputStream的重复利用
*/
public class InputStreamCacher {

private static final Logger logger = LoggerFactory.getLogger(InputStreamCacher.class);

/**
* 将InputStream中的字节保存到ByteArrayOutputStream中。
*/
private ByteArrayOutputStream byteArrayOutputStream = null;

public InputStreamCacher(InputStream inputStream) throws IOException {
if(inputStream == null) {
return ;
}
byteArrayOutputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
try {
while ((len = inputStream.read(buffer)) > -1 ) {
byteArrayOutputStream.write(buffer, 0, len);
}
byteArrayOutputStream.flush();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}

public InputStream getInputStream() {
if (byteArrayOutputStream == null || byteArrayOutputStream.size()<0)
return null;

return new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
}
}


分发的控制类:
@Controller
@RequestMapping("/weixin")
public class WeiXinEventDispatchController {
@Autowired
private WeiXinTokenAndTicket weiXinToken;

@Autowired
private WeiXinMsgService weiXinMsgService;

Logger logger = LoggerFactory.getLogger(WeiXinEventDispatchController.class);

@ResponseBody
@RequestMapping(value="/event", method = {RequestMethod.POST,RequestMethod.GET})
public void event(HttpServletRequest request, HttpServletResponse response) throws IOException, JAXBException {
WeiXinRequestBaseParameter weiXinParameter = WeiXinUtil.installParamter(request);
InputStream is = request.getInputStream();
InputStreamCacher cache =  new InputStreamCacher(is);
String data = XmlUtil.inputStream2Str(cache.getInputStream());
logger.info("============================data=======================================");
logger.info("=" + data);
if(data.contains("<MsgType><![CDATA[event]]></MsgType>")
&& data.contains("<Event><![CDATA[CLICK]]></Event>")){
String result = data.replace("<![CDATA[", "").replace("]]>", "").trim();
JAXBContext context = JAXBContext.newInstance(MenuClickEventDTO.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
MenuClickEventDTO obj = (MenuClickEventDTO)unmarshaller.unmarshal(new StringReader(result));

logger.info(obj.toString());
}else if(data.contains("<MsgType><![CDATA[event]]></MsgType>")
&& data.contains("<Event><![CDATA[VIEW]]></Event>")){
logger.info("发来了VIEW事件");
}else if(data.contains("<MsgType><![CDATA[event]]></MsgType>")
&& data.contains("<Event><![CDATA[subscribe]]></Event>")){
logger.info("订阅公众号");
weiXinMsgService.subscribe(weiXinParameter,data,response);
}else if(data.contains("<MsgType><![CDATA[event]]></MsgType>")
&& data.contains("<Event><![CDATA[unsubscribe]]></Event>")){
logger.info("取消公众号");
weiXinMsgService.unsubscribe(weiXinParameter,data,response);
}else if(data.contains("<MsgType><![CDATA[voice]]></MsgType>")){
logger.info("语言消息");
weiXinMsgService.voiceHandle(weiXinParameter,data,response);
}else if(data.contains("<MsgType><![CDATA[text]]></MsgType>")){
logger.info("文本消息");
weiXinMsgService.textHandle(data,response,cache.getInputStream());
//response.getOutputStream().write(new String(out.toString()).trim().getBytes("UTF-8"));
}else {
logger.info("未知事件");
if(SignUtil.checkSignature(weiXinParameter)) {
logger.info(weiXinParameter.toString());
response.getOutputStream().write(new String(weiXinParameter.getEchostr()).trim().getBytes("UTF-8"));
}
}

}

}
InputStreamCacher cache = new InputStreamCacher(is);

可以看出我先将流缓存起来,然后再用。



把必须类或方法贴出来

/**
* 组装微信请求的数据
* @param request
* @return
*/
public static WeiXinRequestBaseParameter installParamter(HttpServletRequest request){
WeiXinRequestBaseParameter parameter = new WeiXinRequestBaseParameter();
//微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp,nonce参数
parameter.setSignature(request.getParameter("signature"));
//时间戳
parameter.setTimestamp(request.getParameter("timestamp"));
//获取openId
parameter.setOpenid( request.getParameter("openid"));
//随机数
parameter.setNonce(request.getParameter("nonce"));
parameter.setEchostr(request.getParameter("echostr"));
return parameter;
}


import java.io.Serializable;

/**
* @author jack
* @version 1.0
*
*/
public class WeiXinRequestBaseParameter implements Serializable {
/**
*
*/
private static final long serialVersionUID = 2297652335403982945L;
private String signature;
private String timestamp;
private String openid;
private String nonce;
private String echostr;

public WeiXinRequestBaseParameter(String signature, String timestamp, String openid, String nonce, String echostr) {
super();
this.signature = signature;
this.timestamp = timestamp;
this.openid = openid;
this.nonce = nonce;
this.echostr = echostr;
}
public WeiXinRequestBaseParameter() {
super();
}
public String getEchostr() {
return echostr;
}
public String getNonce() {
return nonce;
}
public String getOpenid() {
return openid;
}
public String getSignature() {
return signature;
}
public String getTimestamp() {
return timestamp;
}
public void setEchostr(String echostr) {
this.echostr = echostr;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public void setSignature(String signature) {
this.signature = signature;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
@Override
public String toString() {
return "WeiXinRequestBaseParameter [signature=" + signature + ", timestamp=" + timestamp + ", openid=" + openid
+ ", nonce=" + nonce + ", echostr=" + echostr + "]";
}

}


/**
* @param input
* @return 返回一个xml
* @throws IOException
*/
public static String inputStream2Str(InputStream input) throws IOException{
StringBuffer sb = new StringBuffer("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
InputStreamReader inputReader = new InputStreamReader(input);
BufferedReader buffer = new BufferedReader(inputReader);
String str = "";
while ((str = buffer.readLine()) != null) {
sb.append(new String(str));
}
input.close();
return sb.toString().trim();

}


只涉及文本和emoji处理

@Override
public void textHandle(String data, HttpServletResponse response,InputStream inputStream) throws JAXBException, IOException {
JAXBContext unmarshJc = JAXBContext.newInstance(MsgTextReqDTO.class);
JAXBContext marshJc = JAXBContext.newInstance(MsgTextRespDTO.class);

Unmarshaller unmarshaller = unmarshJc.createUnmarshaller();
MsgTextReqDTO msgTextReqDTO = (MsgTextReqDTO) unmarshaller.unmarshal(inputStream);
//MsgTextReqDTO msgTextReqDTO = (MsgTextReqDTO) unmarshaller.unmarshal(new StringReader(data));
logger.info("Unmarshal: " +msgTextReqDTO.toString());

Marshaller marshaller = marshJc.createMarshaller();
//marshaller.setProperty(Marshaller.JAXB_ENCODING, "gbk");

MsgTextRespDTO msgRespDTO = new MsgTextRespDTO();
//======================硬编码================
msgRespDTO.setContent(msgTextReqDTO.getContent());
msgRespDTO.setCreateTime(WeiXinUtil.createTimestamp());
msgRespDTO.setFromUserName(msgTextReqDTO.getToUserName());
msgRespDTO.setMsgType(msgTextReqDTO.getMsgType());
msgRespDTO.setToUserName(msgTextReqDTO.getFromUserName());
marshaller.marshal(msgRespDTO, response.getOutputStream());

}


实体类
import java.io.Serializable;

import javax.xml.bind.annotation.XmlRootElement;

import org.eclipse.persistence.oxm.annotations.XmlCDATA;
import org.eclipse.persistence.oxm.annotations.XmlPath;

import com.rinlink.intelligent.weixin.entity.WeiXinBaseDTO;

/**
* 文本消息
* @author jack
*
*/
@XmlRootElement(name="xml")
public class MsgTextReqDTO extends WeiXinBaseDTO implements Serializable{
/**
*
*/
private static final long serialVersionUID = -1964882722743733100L;

@XmlCDATA
@XmlPath("Content/text()")
private String content;

@XmlCDATA
@XmlPath("Encrypt/text()")
private String encrypt;

@XmlPath("MsgId/text()")
private String msgId;

public MsgTextReqDTO() {
super();
}

public String getEncrypt() {
return encrypt;
}

public void setEncrypt(String encrypt) {
this.encrypt = encrypt;
}

public String getContent() {
return content;
}

public String getMsgId() {
return msgId;
}

public void setContent(String content) {
this.content = content;
}

public void setMsgId(String msgId) {
this.msgId = msgId;
}

}


import org.eclipse.persistence.oxm.annotations.XmlCDATA;
import org.eclipse.persistence.oxm.annotations.XmlPath;

public class WeiXinBaseDTO {
@XmlCDATA
@XmlPath("ToUserName/text()")
private String toUserName;
@XmlCDATA
@XmlPath("FromUserName/text()")
private String fromUserName;
@XmlPath("CreateTime/text()")
private String createTime;

@XmlCDATA
@XmlPath("MsgType/text()")
private String msgType;
public String getToUserName() {
return toUserName;
}
public String getFromUserName() {
return fromUserName;
}
public String getCreateTime() {
return createTime;
}
public String getMsgType() {
return msgType;
}
public void setToUserName(String toUserName) {
this.toUserName = toUserName;
}
public void setFromUserName(String fromUserName) {
this.fromUserName = fromUserName;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public void setMsgType(String msgType) {
this.msgType = msgType;
}
@Override
public String toString() {
return "WeiXinBaseDTO [toUserName=" + toUserName + ", fromUserName=" + fromUserName + ", createTime="
+ createTime + ", msgType=" + msgType + "]";
}

}


import java.io.Serializable;

import javax.xml.bind.annotation.XmlRootElement;

import org.eclipse.persistence.oxm.annotations.XmlCDATA;
import org.eclipse.persistence.oxm.annotations.XmlPath;

import com.rinlink.intelligent.weixin.entity.WeiXinBaseDTO;

/**
* 回复文本消息
* @author jack
*
*/
/**
* @author Administrator
*
*/
@XmlRootElement(name="xml")
public class MsgTextRespDTO extends WeiXinBaseDTO implements Serializable{
/**
*
*/
private static final long serialVersionUID = -1964882722743733100L;

@XmlCDATA
@XmlPath("Content/text()")
private String content;

public MsgTextRespDTO() {
super();
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}

@Override
public String toString() {
return "MsgTextRespDTO [content=" + content + "]" + "   " + super.toString();
}

}


需要增加一个属性文件

名称:jaxb.properties

内容:javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

文件结构:



注意事项:

1.引入jar

<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>org.eclipse.persistence.moxy</artifactId>
<version>2.7.0-RC1</version>
</dependency>
2.这里采用SpringMVC+Maven工程,可以根据你自己改装一下

3.不需要设置字符编码。正如上面注释的

//marshaller.setProperty(Marshaller.JAXB_ENCODING, "gbk");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: