目录结构
- 项目结构图
- 增加相关源代码
- 注册工具类
-
核心Servlet
- Web工程配置文件
- Maven工程文件
- 上传本地代码到GitHub
- 从GitHub取代码至本地
- 上传工程WAR档至SAE
- 微信客户端测试
- 参考文档
- 完整项目源代码
项目结构图
源代码文件说明
序号 | 文件名 | 说明 | 操作 |
1 | readm.md | 说明文档 | 更新 |
2 | log4j.properties | 日志属性文件 | 新增 |
3 | BaseMessage.java | 消息基类 | 新增 |
4 | TextMessage.java | 文本消息类 | 新增 |
5 | SignUtil.java | 取Token服务类 | 未更新 |
6 | MessageUtil.java | 消息处理工具类 | 新增 |
7 | CoreServlet.java | 核心Servlet,增加doPost()方法 | 更新 |
8 | CoreService.java | 核心服务类,处理前台传过来的请求,并返回响应 | 新增 |
9 | web.xml | Web项目配置文件(这里主要配置Servlet的信息) | 更新 |
10 | index.jsp | 首页文件,显示时间信息,主要用来判断工程是否部署成功 | 未更新 |
增加相关源代码
信息基类
BaseMessage.java
package com.coderdream.model;
/**
* 请求消息基类(普通用户 -> 公众帐号)
*
*/
public class BaseMessage {
/**
* 开发者微信号
*/
private String ToUserName;
/**
* 发送方帐号(一个OpenID)
*/
private String FromUserName;
/**
* 消息创建时间 (整型)
*/
private long CreateTime;
/**
* 消息类型
*/
private String MsgType;
/**
* 消息ID,64位整型
*/
private long MsgId;
public String getToUserName() {
return ToUserName;
}
public void setToUserName(String toUserName) {
ToUserName = toUserName;
}
public String getFromUserName() {
return FromUserName;
}
public void setFromUserName(String fromUserName) {
FromUserName = fromUserName;
}
public long getCreateTime() {
return CreateTime;
}
public void setCreateTime(long createTime) {
CreateTime = createTime;
}
public String getMsgType() {
return MsgType;
}
public void setMsgType(String msgType) {
MsgType = msgType;
}
public long getMsgId() {
return MsgId;
}
public void setMsgId(long msgId) {
MsgId = msgId;
}
}
文本消息类
TextMessage.java
package com.coderdream.model;
/**
* 文本消息
*/
public class TextMessage extends BaseMessage {
/**
* 消息内容
*/
private String Content;
public String getContent() {
return Content;
}
public void setContent(String content) {
Content = content;
}
}
核心服务类
CoreService.java
package com.coderdream.service;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import org.apache.log4j.Logger;
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) {
Date utilDate = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String str = sdf.format(utilDate);
logger.debug(TAG + " ###### log4j debug" + str);
logger.info(TAG + " ###### log4j info" + str);
logger.trace(TAG + " ###### log4j trace" + str);
logger.warn(TAG + " ###### log4j warn" + str);
logger.fatal(TAG + " ###### log4j fatal" + str);
logger.error(TAG + " ###### log4j error" + str);
// 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");
// 回复文本消息
TextMessage textMessage = new TextMessage();
textMessage.setToUserName(fromUserName);
textMessage.setFromUserName(toUserName);
textMessage.setCreateTime(new Date().getTime());
textMessage.setMsgType(MessageUtil.MESSAGE_TYPE_TEXT);
// 文本消息
if (msgType.equals(MessageUtil.MESSAGE_TYPE_TEXT)) {
respContent = "您发送的是文本消息!";
}
logger.debug(TAG + " respContent: " + respContent);
// 设置文本消息的内容
textMessage.setContent(respContent);
// 将文本消息对象转换成xml
respXml = MessageUtil.messageToXml(textMessage);
logger.debug(TAG + " respXml: " + respXml);
} catch (Exception e) {
e.printStackTrace();
}
return respXml;
}
}
核心Servlet
CoreServlet.java
package com.coderdream.servlet;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import com.coderdream.service.CoreService;
import com.coderdream.util.SignUtil;
/**
* 请求处理的核心类
*
*/
public class CoreServlet extends HttpServlet {
public static String TAG = "CoreServlet";
private Logger logger = Logger.getLogger(CoreServlet.class);
private static final long serialVersionUID = 4440739483644821986L;
/**
* 请求校验(确认请求来自微信服务器)
*/
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 微信加密签名
String signature = request.getParameter("signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
PrintWriter out = response.getWriter();
// 请求校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
out.print(echostr);
}
out.close();
out = null;
}
/**
* 请求校验与处理
*/
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Date utilDate = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String str = sdf.format(utilDate);
logger.debug(TAG + " ###### log4j debug" + str);
logger.info(TAG + " ###### log4j info" + str);
logger.trace(TAG + " ###### log4j trace" + str);
logger.warn(TAG + " ###### log4j warn" + str);
logger.fatal(TAG + " ###### log4j fatal" + str);
logger.error(TAG + " ###### log4j error" + str);
// 将请求、响应的编码均设置为UTF-8(防止中文乱码)
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
// 接收参数微信加密签名、 时间戳、随机数
String signature = request.getParameter("signature");
String timestamp = request.getParameter("timestamp");
String nonce = request.getParameter("nonce");
PrintWriter out = response.getWriter();
// 请求校验
if (SignUtil.checkSignature(signature, timestamp, nonce)) {
// 从request中取得输入流
InputStream inputStream = request.getInputStream();
CoreService coreService = new CoreService();
// 调用核心服务类接收处理请求
String respXml = coreService.processRequest(inputStream);
out.print(respXml);
}
out.close();
out = null;
}
}
消息处理工具类
MessageUtil.java
package com.coderdream.util;
import java.io.InputStream;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.coderdream.model.TextMessage;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
/**
* 消息处理工具类
*
*/
public class MessageUtil {
public static String TAG = "MessageUtil";
private static Logger logger = Logger.getLogger(MessageUtil.class);
// 请求消息类型:文本
public static final String MESSAGE_TYPE_TEXT = "text";
/**
* 解析微信发来的请求(XML)
*
* @param request
* @return Map<String, String>
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static Map<String, String> parseXml(InputStream inputStream) throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();
logger.debug(TAG + " begin");
// 从request中取得输入流
// InputStream inputStream = request.getInputStream();
// 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
logger.debug(TAG + " read inputStream");
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements();
// 遍历所有子节点
for (Element e : elementList) {
map.put(e.getName(), e.getText());
logger.debug(TAG + " ###### log4j debug" + e.getName() + " : " + e.getText());
}
// 释放资源
inputStream.close();
inputStream = null;
return map;
}
/**
* 扩展xstream使其支持CDATA
*/
private static XStream xstream = new XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有xml节点的转换都增加CDATA标记
boolean cdata = true;
@SuppressWarnings("rawtypes")
public void startNode(String name, Class clazz) {
super.startNode(name, clazz);
}
protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});
/**
* 文本消息对象转换成xml
*
* @param textMessage
* 文本消息对象
* @return xml
*/
public static String messageToXml(TextMessage textMessage) {
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
}
Web工程配置文件
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>weixin</display-name> <servlet> <servlet-name>coreServlet</servlet-name> <servlet-class>com.coderdream.servlet.CoreServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>coreServlet</servlet-name> <url-pattern>/coreServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
Maven工程文件
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.coderdream</groupId> <artifactId>wxquan</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>wxquan Maven Webapp</name> <url>http://maven.apache.org</url> <dependencies> <!-- 测试的时候用到,打包的时候没有 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- 编译的时候用到,打包的时候没有 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency> <!-- 编译的时候用到,打包的时候没有 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>2.1</version> <scope>provided</scope> </dependency> <!-- 日志包 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.5</version> </dependency> <!-- 打包的时候剔除 xml-apis-1.0.b2.jar SAE中不支持 --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> <exclusions> <exclusion> <groupId>xml-apis</groupId> <artifactId>xml-apis</artifactId> </exclusion> </exclusions> </dependency> <!-- 打包的时候剔除 xml-apis-1.0.b2.jar SAE中不支持 --> <!-- 这个jar必须用1.4.7的高版本,否则SAE不支持 --> <!-- 详细原因:http://blog.csdn.net/lyq8479/article/details/38878543 --> <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.7</version> </dependency> </dependencies> <build> <finalName>wxquan</finalName> </build> </project>
上传本地代码到GitHub
将新增和修改过的代码上传到GitHub
提交成功后,刷新浏览器,查询GitHub中的项目信息:
从GitHub取代码至本地
先在eclipse中设置Git,Windows -> Preferences ->Team -> Git -> Configuration -> Repository Settings,点击“Open”按钮,打开config文件,按如下内容更新:
[core]
repositoryformatversion = 0
filemode = false
logallrefupdates = true
[branch "master"]
remote = origin
merge = refs/heads/master
[remote "origin"]
url = git@github.com:CoderDream/wxquan.git
fetch = +refs/heads/*:refs/remotes/origin/*
push = refs/heads/master:refs/heads/master
更新后的效果如下:
从GitHub上取文件:选择工程,点击右键,Team -> Pull:
弹出如下界面,说明本地和GitHub库有差异,即GitHub库中新增了README.md文件,点击“OK”按钮即可下载到本地。
上传工程WAR档至SAE
将eclipse中的工程导出为wxquan.war档,上传到SAE中,更新已有的版本。
微信客户端测试
登录微信网页版:https://wx.qq.com/
输入“测试”,返回“您发送的是文本消息”,如下图所示:
参考文档
完整源代码