微信公众平台开发实战(05) 历史上的今天

实现历史上的今天功能:

  • 接受“历史MMDD”的输入;
  • 如果只输入“历史”,则输出当前日期的历史;
  • 如果输入“历史1022”,则输出“10月22日”的历史

目录结构

  • 项目结构图
  • 增加和修改相关源代码
    1. 历史实体类
    2. 历史操作类
    3. 历史服务类
    4. 历史表和数据脚本文件
    5. 核心Service

    6. 消息工具类
  • 上传本地代码到GitHub
  • 上传工程WAR档至SAE
  • 微信客户端测试
  • 参考文档
  • 完整项目源代码

项目结构图


 

源代码文件说明

序号 文件名 说明 操作
1 History.java 历史实体类 新增
2 HistoryDao.java 历史操作类 新增
3 TodayInHistoryService.java 历史上的今天服务类 新增
4 history.sql 历史表和数据脚本文件 新增
5 CoreService.java 核心服务类,新增处理各种输入,返回不同图文信息 更新
6 MessageUtil.java 新增生成图文信息的方法 更新

 

增加和修改相关源代码

历史实体类

History.java

package com.coderdream.bean;

/**
 * 历史
 * 
 * @author CoderDream
 * 
 */
public class History {
	private String day;

	private String event;

	public String getDay() {
		return day;
	}

	public void setDay(String day) {
		this.day = day;
	}

	public String getEvent() {
		return event;
	}

	public void setEvent(String event) {
		this.event = event;
	}

}

历史操作类 

HistoryDao.java

package com.coderdream.dao;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

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

import com.coderdream.bean.History;
import com.coderdream.util.DBUtil;

public class HistoryDao {

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

	public static List<History> getHistoryList(String dayStr) {
		List<History> list = new ArrayList<History>();
		Connection connection = null;
		Statement stmt = null;
		ResultSet rs = null;
		// 检索数据
		try {
			connection = DBUtil.getConnection();
			stmt = connection.createStatement();
			int number = stmt.executeUpdate("prepare mystmt from 'select day,event from history where day = ?'");
			if (null == dayStr || "".equals(dayStr.trim())) {
				DateFormat df = new SimpleDateFormat("MMdd");
				dayStr = df.format(Calendar.getInstance().getTime());
			}

			stmt.execute("set @day='" + dayStr + "'");
			rs = stmt.executeQuery("execute mystmt using @day");
			System.out.println(number);

			ResultSetMetaData rsmd = rs.getMetaData(); // 表的字段属性变量
			// 按字段属性输出表的数据名
			for (int i = 1; i <= rsmd.getColumnCount(); i++) {
				logger.info(rsmd.getColumnName(i) + "\t");
			}
			logger.info("\n--------------------------------------\n");
			History history = null;
			while (rs.next()) {
				history = new History();
				String day = rs.getString("day");
				String event = rs.getString("event");
				history.setDay(day);
				history.setEvent(event);
				logger.info("%-8d%-8d%-12s\n", day, event);
				list.add(history);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
	}

	public static void main(String[] args) {
		List<History> list = getHistoryList("0220");
		for (Iterator<History> iterator = list.iterator(); iterator.hasNext();) {
			History history = iterator.next();
			System.out.println(history.getDay() + ":" + history.getEvent());
		}

		List<History> list2 = getHistoryList("");
		for (Iterator<History> iterator = list2.iterator(); iterator.hasNext();) {
			History history = iterator.next();
			System.out.println(history.getDay() + ":" + history.getEvent());
		}
	}
}

 

历史上的今天服务类

TodayInHistoryService.java

package com.coderdream.service;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.coderdream.bean.History;
import com.coderdream.dao.HistoryDao;

/**
 * 历史上的今天查询服务
 * 
 * 
 */
public class TodayInHistoryService {

	/**
	 * 发起http get请求获取网页源代码
	 * 
	 * @param requestUrl
	 * @return
	 */
	private static String httpRequest(String requestUrl) {
		StringBuffer buffer = null;

		try {
			// 建立连接
			URL url = new URL(requestUrl);
			HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
			httpUrlConn.setDoInput(true);
			httpUrlConn.setRequestMethod("GET");

			// 获取输入流
			InputStream inputStream = httpUrlConn.getInputStream();
			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

			// 读取返回结果
			buffer = new StringBuffer();
			String str = null;
			while ((str = bufferedReader.readLine()) != null) {
				buffer.append(str);
			}

			// 释放资源
			bufferedReader.close();
			inputStreamReader.close();
			inputStream.close();
			httpUrlConn.disconnect();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return buffer.toString();
	}

	/**
	 * 从html中抽取出历史上的今天信息
	 * 
	 * @param html
	 * @return
	 */
	private static String extract(String html) {
		StringBuffer buffer = null;
		// 日期标签:区分是昨天还是今天
		String dateTag = getMonthDay(0);

		Pattern p = Pattern.compile("(.*)(<div class=\"listren\">)(.*?)(</div>)(.*)");
		Matcher m = p.matcher(html);
		if (m.matches()) {
			buffer = new StringBuffer();
			if (m.group(3).contains(getMonthDay(-1)))
				dateTag = getMonthDay(-1);

			// 拼装标题
			buffer.append("≡≡ ").append("历史上的").append(dateTag).append(" ≡≡").append("\n\n");

			// 抽取需要的数据
			for (String info : m.group(3).split("  ")) {
				info = info.replace(dateTag, "").replace("(图)", "").replaceAll("</?[^>]+>", "")
								.replaceAll("&nbsp;&nbsp;", "").trim();
				// 在每行末尾追加2个换行符
				if (!"".equals(info)) {
					buffer.append(info).append("\n\n");
				}
			}
		}
		// 将buffer最后两个换行符移除并返回
		return (null == buffer) ? null : buffer.substring(0, buffer.lastIndexOf("\n\n"));
	}

	/**
	 * 获取前/后n天日期(M月d日)
	 * 
	 * @return
	 */
	private static String getMonthDay(int diff) {
		DateFormat df = new SimpleDateFormat("M月d日");
		Calendar c = Calendar.getInstance();
		c.add(Calendar.DAY_OF_YEAR, diff);
		return df.format(c.getTime());
	}

	/**
	 * 封装历史上的今天查询方法,供外部调用
	 * 
	 * @return
	 */
	public static String getTodayInHistoryInfo() {
		// 获取网页源代码
		String html = httpRequest("http://www.rijiben.com/");
		// 从网页中抽取信息
		String result = extract(html);

		return result;
	}

	/**
	 * 封装历史上的今天查询方法,供外部调用
	 * 
	 * @return
	 */
	public static String getTodayInHistoryInfoFromDB(String dayString) {
		// 从网页中抽取信息
		StringBuffer result = new StringBuffer(dayString + "\n");
		result.append("========" + "\n");
		List<History> list = HistoryDao.getHistoryList(dayString);
		for (Iterator<History> iterator = list.iterator(); iterator.hasNext();) {
			History history = iterator.next();
			System.out.println(history.getDay() + ":" + history.getEvent());
			result.append(history.getEvent() + "\n");
		}

		return result.toString();
	}

	/**
	 * 通过main在本地测试
	 * 
	 * @param args
	 */
	public static void main(String[] args) {

		// System.setProperty("http.proxySet", "true");
		// System.setProperty("http.proxyHost", "proxy.jpn.hp.com");
		// System.setProperty("http.proxyPort", "8080");

		String info = getTodayInHistoryInfo();
		System.out.println(info);

		// System.out.println(DateUtil.getMonthDayMMdd(0));
	}
}

 

核心服务类

更新代码后,能接受“历史MMDD”的输入;

  • 如果只输入“历史”,则输出当前日期的历史;
  • 如果输入“历史1022”,则输出“10月22日”的历史。

CoreService.java

package com.coderdream.service;

import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.coderdream.bean.Logging;
import com.coderdream.dao.LoggingDao;
import com.coderdream.model.Article;
import com.coderdream.model.NewsMessage;
import com.coderdream.model.TextMessage;
import com.coderdream.util.MessageUtil;

/**
 * 核心服务类
 */
public class CoreService {

	public static String TAG = "CoreService";

	private Logger logger = Logger.getLogger(CoreService.class);

	/**
	 * 处理微信发来的请求
	 * 
	 * @param request
	 * @return xml
	 */
	public String processRequest(InputStream inputStream) {
		logger.debug(TAG + " #1# processRequest");
		SimpleDateFormat f_timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
		Logging logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG,
						"#1# processRequest");
		LoggingDao loggingDao = new LoggingDao();
		loggingDao.addLogging(logging);
		// xml格式的消息数据
		String respXml = null;
		// 默认返回的文本消息内容
		String respContent = "未知的消息类型!";
		try {
			// 调用parseXml方法解析请求消息
			Map<String, String> requestMap = MessageUtil.parseXml(inputStream);
			// 发送方帐号
			String fromUserName = requestMap.get("FromUserName");
			// 开发者微信号
			String toUserName = requestMap.get("ToUserName");
			// 消息类型
			String msgType = requestMap.get("MsgType");
			String logStr = "#2# fromUserName: " + fromUserName + ", toUserName: " + toUserName + ", msgType: "
							+ msgType;
			logger.debug(TAG + logStr);
			logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG, logStr);
			loggingDao.addLogging(logging);

			// 回复文本消息
			TextMessage textMessage = new TextMessage();
			textMessage.setToUserName(fromUserName);
			textMessage.setFromUserName(toUserName);
			textMessage.setCreateTime(new Date().getTime());
			textMessage.setMsgType(MessageUtil.MESSAGE_TYPE_TEXT);
			logStr = "#3# textMessage: " + textMessage.toString();
			logger.debug(TAG + logStr);
			logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG, logStr);
			loggingDao.addLogging(logging);

			// 文本消息
			if (msgType.equals(MessageUtil.MESSAGE_TYPE_TEXT)) {
				respContent = "您发送的是文本消息!";

				// 接收用户发送的文本消息内容
				String content = requestMap.get("Content");

				// 创建图文消息
				NewsMessage newsMessage = new NewsMessage();
				newsMessage.setToUserName(fromUserName);
				newsMessage.setFromUserName(toUserName);
				newsMessage.setCreateTime(new Date().getTime());
				newsMessage.setMsgType(MessageUtil.MESSAGE_TYPE_NEWS);
				// newsMessage.setFuncFlag(0);

				List<Article> articleList = new ArrayList<Article>();

				// 如果以“历史”2个字开头
				if (content.startsWith("历史")) {
					// 将歌曲2个字及歌曲后面的+、空格、-等特殊符号去掉
					String dayStr = content.substring(2);

					// 如果只输入历史两个字,在输出当天的历史
					if (null == dayStr || "".equals(dayStr.trim())) {
						DateFormat df = new SimpleDateFormat("MMdd");
						dayStr = df.format(Calendar.getInstance().getTime());
					}

					respContent = TodayInHistoryService.getTodayInHistoryInfoFromDB(dayStr);

					textMessage.setContent(respContent);
					// 将图文消息对象转换成xml字符串
					return MessageUtil.messageToXml(textMessage);
				}
				// 单图文消息
				else if ("1".equals(content)) {
					Article article = new Article();
					article.setTitle("微信公众帐号开发教程Java版");
					article.setDescription("柳峰,80后,微信公众帐号开发经验4个月。为帮助初学者入门,特推出此系列教程,也希望借此机会认识更多同行!");
					article.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");
					article.setUrl("http://blog.csdn.net/lyq8479?toUserName=" + fromUserName + "&toUserName="
									+ toUserName);
					articleList.add(article);
					// 设置图文消息个数
					newsMessage.setArticleCount(articleList.size());
					// 设置图文消息包含的图文集合
					newsMessage.setArticles(articleList);
					// 将图文消息对象转换成xml字符串
					return MessageUtil.messageToXml(newsMessage);
				}
				// 单图文消息---不含图片
				else if ("2".equals(content)) {
					Article article = new Article();
					article.setTitle("微信公众帐号开发教程Java版");
					// 图文消息中可以使用QQ表情、符号表情
					article.setDescription("柳峰,80后,"
					// + emoji(0x1F6B9)
									+ ",微信公众帐号开发经验4个月。为帮助初学者入门,特推出此系列连载教程,也希望借此机会认识更多同行!\n\n目前已推出教程共12篇,包括接口配置、消息封装、框架搭建、QQ表情发送、符号表情发送等。\n\n后期还计划推出一些实用功能的开发讲解,例如:天气预报、周边搜索、聊天功能等。");
					// 将图片置为空
					article.setPicUrl("");
					article.setUrl("http://blog.csdn.net/lyq8479?toUserName=" + fromUserName + "&toUserName="
									+ toUserName);
					articleList.add(article);
					newsMessage.setArticleCount(articleList.size());
					newsMessage.setArticles(articleList);
					return MessageUtil.messageToXml(newsMessage);
				}
				// 多图文消息
				else if ("3".equals(content)) {
					Article article1 = new Article();
					article1.setTitle("微信公众帐号开发教程\n引言");
					article1.setDescription("");
					article1.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");
					article1.setUrl("http://blog.csdn.net/lyq8479/article/details/8937622?toUserName=" + fromUserName
									+ "&toUserName=" + toUserName);

					Article article2 = new Article();
					article2.setTitle("第2篇\n微信公众帐号的类型");
					article2.setDescription("");
					article2.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");
					article2.setUrl("http://blog.csdn.net/lyq8479/article/details/8941577?toUserName=" + fromUserName
									+ "&toUserName=" + toUserName);

					Article article3 = new Article();
					article3.setTitle("关注页面");
					article3.setDescription("关注页面");
					article3.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");
					article3.setUrl("http://wxquan.sinaapp.com/follow.jsp?toUserName=" + fromUserName + "&toUserName="
									+ toUserName);

					articleList.add(article1);
					articleList.add(article2);
					articleList.add(article3);
					newsMessage.setArticleCount(articleList.size());
					newsMessage.setArticles(articleList);
					return MessageUtil.messageToXml(newsMessage);
				}
				// 多图文消息---首条消息不含图片
				else if ("4".equals(content)) {
					Article article1 = new Article();
					article1.setTitle("微信公众帐号开发教程Java版");
					article1.setDescription("");
					// 将图片置为空
					article1.setPicUrl("");
					article1.setUrl("http://blog.csdn.net/lyq8479");

					Article article2 = new Article();
					article2.setTitle("第4篇\n消息及消息处理工具的封装");
					article2.setDescription("");
					article2.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");
					article2.setUrl("http://blog.csdn.net/lyq8479/article/details/8949088?toUserName=" + fromUserName
									+ "&toUserName=" + toUserName);

					Article article3 = new Article();
					article3.setTitle("第5篇\n各种消息的接收与响应");
					article3.setDescription("");
					article3.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");
					article3.setUrl("http://blog.csdn.net/lyq8479/article/details/8952173?toUserName=" + fromUserName
									+ "&toUserName=" + toUserName);

					Article article4 = new Article();
					article4.setTitle("第6篇\n文本消息的内容长度限制揭秘");
					article4.setDescription("");
					article4.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");
					article4.setUrl("http://blog.csdn.net/lyq8479/article/details/8967824?toUserName=" + fromUserName
									+ "&toUserName=" + toUserName);

					articleList.add(article1);
					articleList.add(article2);
					articleList.add(article3);
					articleList.add(article4);
					newsMessage.setArticleCount(articleList.size());
					newsMessage.setArticles(articleList);
					return MessageUtil.messageToXml(newsMessage);
				}
				// 多图文消息---最后一条消息不含图片
				else if ("5".equals(content)) {
					Article article1 = new Article();
					article1.setTitle("第7篇\n文本消息中换行符的使用");
					article1.setDescription("");
					article1.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");
					article1.setUrl("http://blog.csdn.net/lyq8479/article/details/9141467?toUserName=" + fromUserName
									+ "&toUserName=" + toUserName);

					Article article2 = new Article();
					article2.setTitle("第8篇\n文本消息中使用网页超链接");
					article2.setDescription("");
					article2.setPicUrl("http://wxquan.sinaapp.com/meal.jpg");
					article2.setUrl("http://blog.csdn.net/lyq8479/article/details/9157455?toUserName=" + fromUserName
									+ "&toUserName=" + toUserName);

					Article article3 = new Article();
					article3.setTitle("如果觉得文章对你有所帮助,请通过博客留言或关注微信公众帐号xiaoqrobot来支持柳峰!");
					article3.setDescription("");
					// 将图片置为空
					article3.setPicUrl("");
					article3.setUrl("http://blog.csdn.net/lyq8479");

					articleList.add(article1);
					articleList.add(article2);
					articleList.add(article3);
					newsMessage.setArticleCount(articleList.size());
					newsMessage.setArticles(articleList);
					// respContent = messageUtil.messageToXml(newsMessage);
					return MessageUtil.messageToXml(newsMessage);
				}
			}
			// 图片消息
			else if (msgType.equals(MessageUtil.MESSAGE_TYPE_IMAGE)) {
				respContent = "您发送的是图片消息!";
			}
			// 语音消息
			else if (msgType.equals(MessageUtil.MESSAGE_TYPE_VOICE)) {
				respContent = "您发送的是语音消息!";
			}
			// 视频消息
			else if (msgType.equals(MessageUtil.MESSAGE_TYPE_VIDEO)) {
				respContent = "您发送的是视频消息!";
			}
			// 地理位置消息
			else if (msgType.equals(MessageUtil.MESSAGE_TYPE_LOCATION)) {
				respContent = "您发送的是地理位置消息!";
			}
			// 链接消息
			else if (msgType.equals(MessageUtil.MESSAGE_TYPE_LINK)) {
				respContent = "您发送的是链接消息!";
			}
			// 事件推送
			else if (msgType.equals(MessageUtil.MESSAGE_TYPE_EVENT)) {
				// 事件类型
				String eventType = requestMap.get("Event");
				// 关注
				if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
					respContent = "谢谢您的关注!";
				}
				// 取消关注
				else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
					// TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
				}
				// 扫描带参数二维码
				else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
					// TODO 处理扫描带参数二维码事件
				}
				// 上报地理位置
				else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {
					// TODO 处理上报地理位置事件
				}
				// 自定义菜单
				else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
					// TODO 处理菜单点击事件
				}
			}

			logStr = "#4# respContent: " + respContent;
			logger.debug(TAG + logStr);
			logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG, logStr);
			loggingDao.addLogging(logging);

			// 设置文本消息的内容
			textMessage.setContent(respContent);
			// 将文本消息对象转换成xml
			respXml = MessageUtil.messageToXml(textMessage);
			logStr = "#5# respXml: " + respXml;
			logger.debug(TAG + logStr);
			logging = new Logging(f_timestamp.format(Calendar.getInstance().getTime()), "DEBUG", TAG, logStr);
			loggingDao.addLogging(logging);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return respXml;
	}
}

 

上传本地代码到GitHub

将新增和修改过的代码上传到GitHub



上传工程WAR档至SAE

将eclipse中的工程导出为wxquan.war档,上传到SAE中,更新已有的版本。

 

微信客户端测试

 登录微信网页版:https://wx.qq.com/

 输入“历史1001”和“历史”,返回不同的图文信息。


 
 

 

参考文档

  1.  

完整源代码

猜你喜欢

转载自coderdream.iteye.com/blog/2147650