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

概述: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");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值