目录结构
- 项目结构图
- 增加相关源代码
- 日志实体类
- 日志访问类
- 日志访问测试类
- 测试工具类
- 数据库工具类
-
核心Service
- Maven工程文件
- 上传本地代码到GitHub
- 上传工程WAR档至SAE
- 微信客户端测试
- 查看SAE数据库
- 参考文档
- 完整项目源代码
项目结构图
源代码文件说明
序号 | 文件名 | 说明 | 操作 |
1 | readme.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 | 首页文件,显示时间信息,主要用来判断工程是否部署成功 | 未更新 |
11 | Logging.java | 日志实体类 | 新增 |
12 | LoggingDao.java | 日志操作类 | 新增 |
13 | LoggingDaoTest.java | 日志测试类 | 新增 |
14 | EntitiesHelper.java | 测试辅助类 | 新增 |
15 | jdbc.properties | 数据库配置文件 | 新增 |
16 | DBUtil.java | 数据库工具类 | 新增 |
17 | logging.xml | 测试数据文件 | 新增 |
18 | logging_add.xml | 测试数据文件 | 新增 |
增加相关源代码
日志实体类
Logging.java
package com.coderdream.bean;
public class Logging {
// `id` int(11) NOT NULL AUTO_INCREMENT,
private int id;
// `log_date` datetime DEFAULT NULL,
// private Timestamp logDate; 由于MySQL不能存入带毫米数的Timestamp,这里直接存字符串
private String logDate;
// `log_level` varchar(64) DEFAULT NULL,
private String logLevel;
// `location` varchar(256) DEFAULT NULL,
private String location;
// `message` varchar(1024) DEFAULT NULL,
private String message;
public Logging() {
}
public Logging(int id, String logDate, String logLevel, String location, String message) {
this.id = id;
this.logDate = logDate;
this.logLevel = logLevel;
this.location = location;
this.message = message;
}
public Logging(String logDate, String logLevel, String location, String message) {
this.logDate = logDate;
this.logLevel = logLevel;
this.location = location;
this.message = message;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getLogDate() {
return logDate;
}
public void setLogDate(String logDate) {
this.logDate = logDate;
}
public String getLogLevel() {
return logLevel;
}
public void setLogLevel(String logLevel) {
this.logLevel = logLevel;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "Logging [id=" + id + ", logDate=" + logDate + ", logLevel=" + logLevel + ", location=" + location
+ ", message=" + message + "]";
}
}
日志操作类
LoggingDao.java
package com.coderdream.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.apache.log4j.Logger;
import com.coderdream.bean.Logging;
import com.coderdream.util.DBUtil;
public class LoggingDao {
private String location;
public static String TAG = "LoggingDao";
private Logger logger = Logger.getLogger(LoggingDao.class);
public LoggingDao() {
}
public LoggingDao(String location) {
this.location = location;
}
public int addLogging(Logging logging) {
logger.debug(TAG + "###0###");
String sql = "INSERT INTO logging (log_date, log_level, location, message) VALUES (?,?,?,?)";
int count = 0;
Connection con = null;
PreparedStatement ps = null;
try {
con = DBUtil.getConnection();
logger.debug(TAG + con);
ps = con.prepareStatement(sql);
ps.setString(1, logging.getLogDate());
ps.setString(2, logging.getLogLevel());
ps.setString(3, logging.getLocation());
ps.setString(4, logging.getMessage());
count = ps.executeUpdate();
logger.debug(TAG + "count: " + count);
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.close(ps);
DBUtil.close(con);
}
return count;
}
public int debug(String message) {
if (!logger.isDebugEnabled()) {
return 0;
}
logger.debug(TAG + "###0###");
String sql = "INSERT INTO logging (log_date, log_level, location, message) VALUES (?,?,?,?)";
int count = 0;
Connection con = null;
PreparedStatement pre = null;
try {
con = DBUtil.getConnection();
logger.debug(TAG + " ###2### Connection: " + con);
pre = con.prepareStatement(sql);
logger.debug(TAG + " ###3### PreparedStatement: " + pre);
Date date = Calendar.getInstance().getTime();
SimpleDateFormat f_timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
String logTimestampStr = f_timestamp.format(date);
pre.setString(1, logTimestampStr);
pre.setString(2, "DEBUG");
pre.setString(3, location);
pre.setString(4, message);
count = pre.executeUpdate();
logger.debug(TAG + "###4### count: " + count);
} catch (Exception e) {
logger.debug(TAG + "###5### Exception: " + e.getMessage());
e.printStackTrace();
} finally {
DBUtil.close(pre);
DBUtil.close(con);
}
return count;
}
public static int debug(String location, String message) {
if (!Logger.getLogger(LoggingDao.class).isDebugEnabled()) {
return 0;
}
String sql = "INSERT INTO logging (log_date, log_level, location, message) VALUES (?,?,?,?)";
int count = 0;
Connection con = null;
PreparedStatement pre = null;
try {
con = DBUtil.getConnection();
pre = con.prepareStatement(sql);
Date date = Calendar.getInstance().getTime();
SimpleDateFormat f_timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
String logTimestampStr = f_timestamp.format(date);
pre.setString(1, logTimestampStr);
pre.setString(2, "DEBUG");
pre.setString(3, location);
pre.setString(4, message);
count = pre.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.close(pre);
DBUtil.close(con);
}
return count;
}
public int error(String message) {
logger.debug(TAG + "###0###");
String sql = "INSERT INTO logging (log_date, log_level, location, message) VALUES (?,?,?,?)";
int count = 0;
Connection con = null;
PreparedStatement pre = null;
try {
con = DBUtil.getConnection();
logger.debug(TAG + con);
pre = con.prepareStatement(sql);
Date date = Calendar.getInstance().getTime();
SimpleDateFormat f_timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
String logTimestampStr = f_timestamp.format(date);
pre.setString(1, logTimestampStr);
pre.setString(2, "ERROR");
pre.setString(3, location);
pre.setString(4, message);
count = pre.executeUpdate();
logger.debug(TAG + "count: " + count);
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.close(pre);
DBUtil.close(con);
}
return count;
}
public static int error(String location, String message) {
String sql = "INSERT INTO logging (log_date, log_level, location, message) VALUES (?,?,?,?)";
int count = 0;
Connection con = null;
PreparedStatement pre = null;
try {
con = DBUtil.getConnection();
pre = con.prepareStatement(sql);
Date date = Calendar.getInstance().getTime();
SimpleDateFormat f_timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
String logTimestampStr = f_timestamp.format(date);
pre.setString(1, logTimestampStr);
pre.setString(2, "ERROR");
pre.setString(3, location);
pre.setString(4, message);
count = pre.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.close(pre);
DBUtil.close(con);
}
return count;
}
PreparedStatement pre;
ResultSet rs;
/**
* @author help
*
* 显示所有记录
* @return
*/
public List<Logging> findLoggings() {
String sql = "select * from logging order by id";
List<Logging> list = new ArrayList<Logging>();
// 获取prepareStatement对象
Connection con = null;
try {
con = DBUtil.getConnection();
pre = con.prepareStatement(sql);
rs = pre.executeQuery();
while (rs.next()) {
Logging logging = new Logging();
logging.setId(rs.getInt("id"));
logging.setLogDate(rs.getString("log_date"));
logging.setLogLevel(rs.getString("log_level"));
logging.setLocation(rs.getString("location"));
logging.setMessage(rs.getString("message"));
list.add(logging);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.close(pre);
DBUtil.close(con);
}
return list;
}
/**
* @author help
*
* 显示所有记录
* @return
*/
public Logging findLogging(int id) {
String sql = "select * from logging where id=?";
List<Logging> list = new ArrayList<Logging>();
// 获取prepareStatement对象
Connection con = null;
try {
con = DBUtil.getConnection();
pre = con.prepareStatement(sql);
pre.setInt(1, id);
rs = pre.executeQuery();
while (rs.next()) {
Logging logging = new Logging();
logging.setId(rs.getInt("id"));
logging.setLogDate(rs.getString("log_date"));
logging.setLogLevel(rs.getString("log_level"));
logging.setLocation(rs.getString("location"));
logging.setMessage(rs.getString("message"));
list.add(logging);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil.close(pre);
DBUtil.close(con);
}
if (null != list && 0 < list.size()) {
return list.get(0);
}
return null;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
}
日志操作测试类
LoggingDaoTest.java
package com.coderdream.dao;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.dbunit.Assertion;
import org.dbunit.DatabaseUnitException;
import org.dbunit.database.DatabaseConnection;
import org.dbunit.database.IDatabaseConnection;
import org.dbunit.database.QueryDataSet;
import org.dbunit.dataset.IDataSet;
import org.dbunit.dataset.ITable;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.dataset.xml.FlatXmlProducer;
import org.dbunit.operation.DatabaseOperation;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.InputSource;
import com.coderdream.bean.Logging;
import com.coderdream.util.DBUtil;
import com.coderdream.util.EntitiesHelper;
/**
* <pre>
* DBUnit使用步骤
* 1)下载地址为http://sourceforge.net/projects/dbunit/files/
* 2)导入DBUnit所需两个jar文件(dbunit.jar和slf4j-api.jar)
* 3)创建DBUnit用到的xml格式的测试数据,xml文件名建议与表名相同
* 4)创建DBUnit的Connection和DataSet,然后开始进行各项测试工作
*
* 使用注解@BeforeClass,在globalInit()执行打开数据库操作;
* 使用注解@AfterClass,在globalDestroy()执行数据库关闭操作;
*
* 使用注解@Before,每次测试执行之前都先执行init()操作;
* 使用注解@After,每次测试执行之后都会执行destroy()操作;
*
* DBUtil提供数据库操作方法。
* </pre>
*
* @author CoderDream
* @date 2014年10月15日
*
*/
public class LoggingDaoTest {
public static String TAG = "LoggingDaoTest";
private static final Logger logger = LoggerFactory.getLogger(LoggingDaoTest.class);
private static Connection conn;
private static IDatabaseConnection dbUnitConn;
private static String DATA_BACKUP_FILE = "dataBackup_logging.xml";
private static String LOGGING_DATA_FILE = "logging.xml";
@BeforeClass
public static void globalInit() {
conn = DBUtil.getConnection();
System.out.println("DB-Unit Get Connection: " + conn);
try {
// DBUnit中用来操作数据文件的Connection需依赖于数据库连接的Connection
dbUnitConn = new DatabaseConnection(conn);
} catch (DatabaseUnitException e) {
e.printStackTrace();
}
}
@AfterClass
public static void globalDestroy() {
DBUtil.close(conn);
if (null != dbUnitConn) {
try {
dbUnitConn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
/**
* 备份数据库中某一张或某几张表的数据,同时将xml文件中的数据插入到数据库中
*/
@Before
public void init() throws Exception {
logger.debug("Before #### init");
// 通过QueryDataSet可以有效的选择要处理的表来作为DataSet
QueryDataSet dataSet = new QueryDataSet(dbUnitConn);
// 这里指定只备份t_logging表中的数据,如果想备份多个表,那就再addTable(tableName)即可
dataSet.addTable("logging");
FlatXmlDataSet.write(dataSet, new FileWriter(DATA_BACKUP_FILE));
}
/**
* 还原表数据
*/
@After
public void destroy() throws Exception {
IDataSet dataSet = new FlatXmlDataSet(new FlatXmlProducer(
new InputSource(new FileInputStream(DATA_BACKUP_FILE))));
DatabaseOperation.CLEAN_INSERT.execute(dbUnitConn, dataSet);
}
/**
* <pre>
* 测试查询方法
* DatabaseOperation类的几个常量值
* CLEAN_INSERT----先删除数据库中的所有数据,然后将xml中的数据插入数据库
* DELETE----------如果数据库存在与xml记录的相同的数据,则删除数据库中的该条数据
* DELETE_ALL------删除数据库中的所有数据
* INSERT----------将xml中的数据插入数据库
* NONE------------nothing to do
* REFRESH---------刷新数据库中的数据
* TRUNCATE_TABLE--清空表中的数据
* UPDATE----------将数据库中的那条数据更新为xml中的数据
* </pre>
*/
@Test
public void testFindLogging() throws Exception {
IDataSet dataSet = new FlatXmlDataSet(new FlatXmlProducer(new InputSource(LoggingDaoTest.class.getClassLoader()
.getResourceAsStream(LOGGING_DATA_FILE))));
DatabaseOperation.TRUNCATE_TABLE.execute(dbUnitConn, dataSet);
DatabaseOperation.CLEAN_INSERT.execute(dbUnitConn, dataSet);
// 下面开始数据测试
LoggingDao loggingDao = new LoggingDao();
Logging logging = loggingDao.findLogging(1);
// 预想结果和实际结果的比较
EntitiesHelper.assertLogging(logging);
}
/**
* 更新,添加,删除等方法,可以利用Assertion.assertEquals() 方法,拿表的整体来比较。
*/
@Test
public void testAddLogging() throws Exception {
IDataSet dataSet = new FlatXmlDataSet(new FlatXmlProducer(new InputSource(LoggingDaoTest.class.getClassLoader()
.getResourceAsStream(LOGGING_DATA_FILE))));
DatabaseOperation.TRUNCATE_TABLE.execute(dbUnitConn, dataSet);
DatabaseOperation.CLEAN_INSERT.execute(dbUnitConn, dataSet);
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String time = df.format(new Date(1413993830024l));
// Timestamp ts = Timestamp.valueOf(time);
String logStr = "FirstLogging";
// 被追加的记录
Logging newLogging = new Logging(time, "DEBUG", TAG, logStr);
// 执行追加 addLogging 方法
LoggingDao loggingDao = new LoggingDao();
int result = loggingDao.addLogging(newLogging);
Assert.assertEquals(1, result);
// 预期结果取得
IDataSet expectedDataSet = new FlatXmlDataSet(new FlatXmlProducer(new InputSource(LoggingDaoTest.class
.getClassLoader().getResourceAsStream("logging_add.xml"))));
ITable expectedTable = expectedDataSet.getTable("logging");
// 实际结果取得(取此时数据库中的数据)
// Creates a dataset corresponding to the entire database
IDataSet databaseDataSet = dbUnitConn.createDataSet();
ITable actualTable = databaseDataSet.getTable("logging");
// 预想结果和实际结果的比较
Assertion.assertEquals(expectedTable, actualTable);
}
}
测试辅助类
EntitiestHelper.java
package com.coderdream.util;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Assert;
import com.coderdream.bean.Logging;
public class EntitiesHelper {
public static void assertLogging(Logging expected, Logging actual) {
Assert.assertNotNull(expected);
Assert.assertEquals(expected.getId(), actual.getId());
Assert.assertEquals(expected.getLogDate(), actual.getLogDate());
Assert.assertEquals(expected.getLogLevel(), actual.getLogLevel());
Assert.assertEquals(expected.getLocation(), actual.getLocation());
Assert.assertEquals(expected.getMessage(), actual.getMessage());
}
public static void assertLogging(Logging expected) {
String logStr = "InitLogging";
// Timestamp sDate = new Timestamp(1413993830024l);
// 2014-10-23 00:03:50.024
// time: 1413993830024
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String time = df.format(new Date(1413993830024l));
Logging baseLogging = new Logging(1, time, "DEBUG", "LoggingDaoTest", logStr);
assertLogging(expected, baseLogging);
}
}
数据库工具类
DBUtil.java
package com.coderdream.util;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;
import java.util.Properties;
public class DBUtil {
public static Connection getConnection() {
Connection con = null;
Properties prop = new Properties();// 属性集合对象
InputStream fis;
try {
fis = DBUtil.class.getClassLoader().getResourceAsStream(
"jdbc.properties");
prop.load(fis);// 将属性文件流装载到Properties对象中
String driver = prop.getProperty("driver");
String username = prop.getProperty("username");
String password = prop.getProperty("password");
String url = prop.getProperty("url");// 使用从库的域名
Map<String, String> envMap = System.getenv();
String os = envMap.get("OS");
// local
if (null != os && "Windows_NT".equals(os.trim())) {
username = prop.getProperty("local.username");
password = prop.getProperty("local.password");
url = prop.getProperty("local.url");
}
// SAE
else {
username = prop.getProperty("sae.username");
password = prop.getProperty("sae.password");
url = prop.getProperty("sae.url");
}
Class.forName(driver).newInstance();
con = DriverManager.getConnection(url, username, password);
} catch (Exception e) {
e.printStackTrace();
}
return con;
}
public static void close(Connection con) {
try {
if (null != con) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(PreparedStatement ps) {
try {
if (null != ps) {
ps.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void close(ResultSet rs) {
try {
if (null != rs) {
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
核心服务类
CoreService.java
package com.coderdream.service;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import org.apache.log4j.Logger;
import com.coderdream.bean.Logging;
import com.coderdream.dao.LoggingDao;
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");
//Timestamp sDate = new Timestamp(Calendar.getInstance().getTime().getTime());
Date date = Calendar.getInstance().getTime();
SimpleDateFormat f_timestamp = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss.SSS");
String logTimestampStr = f_timestamp.format(date);
Logging logging = new Logging(logTimestampStr, "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(logTimestampStr, "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(logTimestampStr, "DEBUG", TAG, logStr);
loggingDao.addLogging(logging);
// 文本消息
if (msgType.equals(MessageUtil.MESSAGE_TYPE_TEXT)) {
respContent = "您发送的是文本消息!";
}
logStr = "#4# respContent: " + respContent;
logger.debug(TAG + logStr);
logging = new Logging(logTimestampStr, "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(logTimestampStr, "DEBUG", TAG, logStr);
loggingDao.addLogging(logging);
} catch (Exception e) {
e.printStackTrace();
}
return respXml;
}
}
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> <properties> <junit.version>4.11</junit.version> <servlet.api.version>2.5</servlet.api.version> <jsp.api.version>2.1</jsp.api.version> <slf4j.version>1.7.5</slf4j.version> <dom4j.version>1.6.1</dom4j.version> <xstream.version>1.4.7</xstream.version> <mysql.version>5.1.17</mysql.version> <dbunit.version>2.4.9</dbunit.version> </properties> <dependencies> <!-- 测试的时候用到,打包的时候没有 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- 编译的时候用到,打包的时候没有 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>${servlet.api.version}</version> <scope>provided</scope> </dependency> <!-- 编译的时候用到,打包的时候没有 --> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>jsp-api</artifactId> <version>${jsp.api.version}</version> <scope>provided</scope> </dependency> <!-- 日志包 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>${slf4j.version}</version> </dependency> <!-- 打包的时候剔除 xml-apis-1.0.b2.jar SAE中不支持 --> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>${dom4j.version}</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>${xstream.version}</version> </dependency> <!-- 编译的时候用到,打包的时候没有,SAE已包含此jar --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.dbunit</groupId> <artifactId>dbunit</artifactId> <version>${dbunit.version}</version> <scope>test</scope> </dependency> </dependencies> <build> <finalName>wxquan</finalName> </build> </project>
上传本地代码到GitHub
将新增和修改过的代码上传到GitHub
上传工程WAR档至SAE
将eclipse中的工程导出为wxquan.war档,上传到SAE中,更新已有的版本。
微信客户端测试
登录微信网页版:https://wx.qq.com/
输入“测试”,返回“您发送的是文本消息”。
查看SAE数据库
查询SAE数据库,发现logging表中已写入相关数据:
参考文档
完整源代码