目录结构
- 项目结构图
- 增加相关源代码
- 日志实体类
- 日志访问类
- 日志访问测试类
- 测试工具类
- 数据库工具类
-
核心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表中已写入相关数据:
参考文档
完整源代码
相关推荐
微信小程序点餐系统微信小程序开发实战项目源码+后台+数据库(毕业设计)微信小程序点餐系统微信小程序开发实战项目源码+后台+数据库(毕业设计)微信小程序点餐系统微信小程序开发实战项目源码+后台+数据库(毕业...
微信公众号平台发开书籍与实例文档 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
微信公众平台应用开发实战-完整扫描版 pdf 版本。 微信公众平台应用开发实战-完整扫描版 pdf 文档。 微信公众平台应用开发实战-完整扫描版.pdf 全书一共9章,在逻辑上分为四大部分:第一部分(第1章)介绍了微信公众...
第二部分(第2、3章)介绍了进行微信公众平台开发所需的准备工作及将应用接入微信公众平台的方法;第三部分(第4、5章)详细介绍了微信公众平台已开放的API,通过实战项目对开发框架进行了系统讲解,读者甚至可以...
微信开发实例 微信公众平台开发教程-深入浅出微信公众平台实战开发(微网站、LBS云、Api接口调用、服务号高级接口)1.微信接口前期准备。由北风网提供,微信开发实例微信公众平台基础篇: 1)微信公众平台简介:开发...
刘捷版微信公众平台企业应用开发实战 Sample源码以及相关SDK
对微信公众平台开发有兴趣的同学 对ASP.NET MVC开发有兴趣的同学 有志进入开发行业的所有同学 课程特色: 最前沿ASP.NET MVC 5、Entity Framework 6、微信公众平台5.2 最全6大功能19个接口用法大揭秘 零基础快速...
本书是微信公众平台应用开发方面的书籍,作者是腾讯公司的软件开发工程师,而且是微信公众平台应用开发的先驱者之一。本书全面介绍了微信公众平台应用开发所需的各项技术,系统解读了微信公众平台开放的API和各项...
《微信公众平台应用开发实战》是微信公众平台应用开发领域的经典著作,作者是腾讯公司的资深软件开发工程师,而且是微信公众平台应用开发的先驱者之一。本书全面介绍了微信公众平台应用开发所需的各项技术,系统解读...
《企业微信公众平台开发实战:再小的个体也有自己的品牌》方倍工作室,2015年,配套源码。
ASP.NET MVC 5 微信公众平台整合开发实战第三部
《微信公众平台开发实战》(php版),手打完美书签,方便导航入阅读
微信公众平台应用开发实战-完整扫描版 PDF扫描版,放心下载。
本书是微信公众平台应用开发领域的经典著作,作者是腾讯公司的资深软件开发工程师,而且是微信公众平台应用开发的先驱者之一。本书全面介绍了微信公众平台应用开发所需的各项技术,系统解读了微信公众平台开放的API...
微信公众平台开发入门教程
第二部分(第2、3章)介绍了进行微信公众平台开发所需的准备工作及将应用接入微信公众平台的方法;第三部分(第4、5章)详细介绍了微信公众平台已开放的API,通过实战项目对开发框架进行了系统讲解,读者甚至可以...
对微信公众平台开发有兴趣的同学 对ASP.NET MVC开发有兴趣的同学 有志进入开发行业的所有同学 课程特色: 最前沿ASP.NET MVC 5、Entity Framework 6、微信公众平台5.2 最全6大功能19个接口用法大揭秘 零基础快速...
微信小程序点餐系统是当前移动互联网时代餐饮业中常见的技术应用,它利用微信小程序平台,为用户提供便捷的在线点餐服务。本项目实战教程将深入探讨如何开发这样一个系统,涵盖从设计、编码到上线的全过程。 一、...