转载请注明出处:http://blog.youkuaiyun.com/xiaojimanman/article/details/45044051
http://www.llwjy.com/blogdetail/6c8ff7985249e119b6b683f9a65d6597.html
个人博客站已经上线了,网址 www.llwjy.com ~欢迎各位吐槽~
-------------------------------------------------------------------------------------------------
在上一篇博客中,我们已经介绍了微信服务器的配置,这篇我们就介绍以下如何针对微信公共号做开发。由于自己现在的微信公共号是个人的,所以现在只能做一些简单的被动回复,等几天公司的公共号到手再开始其他功能的介绍。
在上一篇博客中,在WeiXinServlet类中实现了对服务器时效性的验证,验证通过之后,这些代码就可以不用了,为了之后切换微信公共号,建议只注释掉即可。
接收消息
在服务器接收到请求之后,解析request提交过来的xml,获取相关信息,代码实现如下:
private HashMap<String, String> parseRequestXml(HttpServletRequest request) throws Exception{
// 将解析结果存储在HashMap中
HashMap<String, String> map = new HashMap<String, String>();
Document document = XmlUtil.createFromRequest(request);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements();
// 遍历所有子节点
for (Element e : elementList){
map.put(e.getName(), e.getText());
}
return map;
}
在map中,我们通过map.get("MsgType")可以获取到用户发送消息类型(具体xml结构,参照开发者文档中的
接收消息--接收普通消息),对于不同的消息类型,选择不同的分支,当然这里就先对关注事件和文本消息做响应,其他的部分在之后的文档中介绍。根据消息类型不同选择不同的分支,代码实现如下:
public String reply(HttpServletRequest request) {
try {
HashMap<String, String> map = parseRequestXml(request);
if (map == null) {
return "";
}
String type = map.get("MsgType");
if ("text".equals(type)){
return textMessage(map);
} else if ("event".equals(type)) {
return subscribeMessage(map);
}else {
return "";
}
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
自己也是刚刚开始微信开发,对于微信消息的数据结构了解也不是太多,所以自己就先设计如下的消息结构来封装需要回复的消息内容,Message基类:
/**
*@Description: 微信消息类型
*/
package com.lulei.weixin.model;
public class Message {
private String toUser;
private String fromUser;
public String getToUser() {
return toUser;
}
public void setToUser(String toUser) {
this.toUser = toUser;
}
public String getFromUser() {
return fromUser;
}
public void setFromUser(String fromUser) {
this.fromUser = fromUser;
}
}
回复文本消息TextMessage:
/**
*@Description: 文本消息
*/
package com.lulei.weixin.model;
public class TextMessage extends Message{
private String content;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
接口返回的内容是xml格式的字符串,因此我们需要把javabean转化为固定格式的字符串,所以创建ReplyMessage类,用来转化各种类型的消息,代码实现如下:
/**
*@Description: 微信返回消息模版
*/
package com.lulei.weixin.model;
import java.util.Date;
public class ReplyMessage {
//文本消息模版
private static String textMessageModel = "<xml><ToUserName><![CDATA[_toUser_]]></ToUserName><FromUserName><![CDATA[_fromUser_]]></FromUserName><CreateTime>_time_</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[_content_]]></Content></xml>";
private static String messageNull = "";
/**
* @param message
* @return
* @Author:lulei
* @Description: 创建文本消息
*/
public static String creatTextMessage(TextMessage message){
if (message == null) {
return messageNull;
}
return textMessageModel.replaceAll("_toUser_", message.getToUser())
.replaceAll("_fromUser_", message.getFromUser())
.replace("_content_", message.getContent())
.replace("time_", new Date().getTime()+"");
}
}
结合接收消息部分,我们就可以完成WeiXinService类来完成相关的业务逻辑,代码如下:
/**
*@Description: 微信业务层
*/
package com.lulei.weixin.service;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.httpclient.HttpException;
import org.dom4j.Document;
import org.dom4j.Element;
import com.lulei.crawl.baixiaodu.BaiduRobot;
import com.lulei.util.XmlUtil;
import com.lulei.weixin.model.ReplyMessage;
import com.lulei.weixin.model.TextMessage;
public class WeiXinService {
@SuppressWarnings("unchecked")
private HashMap<String, String> parseRequestXml(HttpServletRequest request) throws Exception{
// 将解析结果存储在HashMap中
HashMap<String, String> map = new HashMap<String, String>();
Document document = XmlUtil.createFromRequest(request);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements();
// 遍历所有子节点
for (Element e : elementList){
map.put(e.getName(), e.getText());
}
return map;
}
/**
* @param request
* @return
* @Author:lulei
* @Description: 应答
*/
public String reply(HttpServletRequest request) {
try {
HashMap<String, String> map = parseRequestXml(request);
if (map == null) {
return "";
}
String type = map.get("MsgType");
if ("text".equals(type)){
return textMessage(map);
} else if ("event".equals(type)) {
return subscribeMessage(map);
}else {
return "";
}
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
/**
* @return
* @throws HttpException
* @throws IOException
* @Author:lulei
* @Description: 应答文本信息
*/
private String textMessage(HashMap<String, String> mes) throws HttpException, IOException{
TextMessage message = new TextMessage();
message.setFromUser(mes.get("ToUserName"));
message.setToUser(mes.get("FromUserName"));
message.setContent(new BaiduRobot(mes.get("Content")).getAnswer());
return ReplyMessage.creatTextMessage(message);
}
/**
* @param mes
* @return
* @throws HttpException
* @throws IOException
* @Author:lulei
* @Description: 事件应答
*/
private String subscribeMessage(HashMap<String, String> mes) throws HttpException, IOException{
TextMessage message = new TextMessage();
message.setFromUser(mes.get("ToUserName"));
message.setToUser(mes.get("FromUserName"));
if ("subscribe".equals(mes.get("Event"))) { //关注应答
message.setContent("欢迎关注小鸡慢慢~\n回复内容可以和我聊天呦~\n回复“笑话”给您说个笑话~\n更过内容等待您挖掘~");
} else {
message.setContent("未知事件");
}
return ReplyMessage.creatTextMessage(message);
}
}
最后一步只需要在上一篇博客中的WeiXinServlet类中添加一个属性,如下:
private static WeiXinService weixin = new WeiXinService();
将parseString方法做如下修改即可:
protected String parseString(HttpServletRequest request) {
//微信首次验证
//return check(request);
//微信应答
return weixin.reply(request);
}
百小度机器人
在上面的代码中,提到了一个百小度机器人的数据采集,对于百小度的介绍可以自行百度,目前这个机器人好像只是小范围测试,自己有幸在测试范围内,所以就对他的接口做了下应用。百小度的信息采集BaiduRobot类还是基于之前介绍的CrawBase类,具体如何模拟分析可以参照之前的相关博客,这里给出具体的实现的源代码:
/**
*@Description:
*/
package com.lulei.crawl.baixiaodu;
import java.io.IOException;
import java.util.HashMap;
import org.apache.commons.httpclient.HttpException;
import com.lulei.crawl.CrawlBase;
import com.lulei.util.DoRegex;
/**
*@Description:
*@Author:lulei
*@Version:1.1.0
*/
public class BaiduRobot extends CrawlBase {
private static HashMap<String, String> params;
private static String answerRegex = "answer\\\\\":\\\\\"(.*?)\\\\\",";
private static String urlModel = "https://sp0.baidu.com/yLsHczq6KgQFm2e88IuM_a/s?sample_name=bear_brain&request_query=%text%&bear_type=2&request_time=1428543613075&callback=jQuery110204140488877892494_1428543517759&_=1428543517773";
static {
params = new HashMap<String, String>();
params.put("Host", "www.baidu.com");
params.put("Referer", "https://www.baidu.com");
params.put("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36");
params.put("cookie", "这里是cookie内容,为了个人帐号安全,这里就省略了");
}
public BaiduRobot(String key) throws HttpException, IOException {
String url = urlModel.replaceAll("%text%", key);
super.readPageByGet(url, "utf-8", params);
}
public String getAnswer(){
return DoRegex.getFirstString(getPageSourceCode(), answerRegex, 1);
}
public static void main(String[] args) throws HttpException, IOException {
// TODO Auto-generated method stub
System.out.println(new BaiduRobot("我怀孕了,怎么办").getPageSourceCode());
}
}
运行结果
这些开发完成之后,在我们的微信公共号中做下测试,效果图如下:
联想
在上述的文本类型的消息中,我们可以对用户发的文本信息做一下简单的过滤,即满足一定的要求,走我们自己的业务逻辑,否则走百小度的聊天接口,这样就可以完成更多的功能:比如业务推广、信息查询等等。