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

来源:互联网 发布:java毫秒转换成分钟 编辑:程序博客网 时间:2024/05/21 15:12

概述: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 {@Autowiredprivate WeiXinTokenAndTicket weiXinToken;@Autowiredprivate 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"));//获取openIdparameter.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;}@Overridepublic 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处理
@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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");

原创粉丝点击