`
CoderDream
  • 浏览: 470774 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

微信公众平台开发实战(03) 运行日志写入SAE数据库

阅读更多

 

目录结构

  • 项目结构图
  • 增加相关源代码
    1. 日志实体类
    2. 日志访问类
    3. 日志访问测试类
    4. 测试工具类
    5. 数据库工具类
    6. 核心Service

    7. 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表中已写入相关数据:

 
 

参考文档

  1.  

完整源代码

  • 大小: 27.5 KB
  • 大小: 176.5 KB
  • 大小: 56.6 KB
0
0
分享到:
评论

相关推荐

    华为OD机试D卷 - 在字符串中找出连续最长的数字串(含“+-”号) - 免费看解析和代码.html

    私信博主免费获取真题解析以及代码

    node-v6.11.0-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    23-22.渗透测试-敏感信息收集工具汇总.mp4

    23-22.渗透测试-敏感信息收集工具汇总.mp4

    ZCANPRO安装包ZCANPRO-Setup-V2.2.6(20230327)

    ZCANPRO安装包

    单片机外文翻译at89s52单片机单片机.doc

    单片机外文翻译at89s52单片机单片机.doc

    基于AT89S52单片机的数字温度计设计.doc

    基于AT89S52单片机的数字温度计设计.doc

    华为OD机试D卷 - 最长子字符串的长度(一)- 免费看解析和代码.html

    私信博主免费获取真题解析以及代码

    node-v6.12.0-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    Screenshot_2024-05-10-20-21-01-857_com.chaoxing.mobile.jpg

    Screenshot_2024-05-10-20-21-01-857_com.chaoxing.mobile.jpg

    基于mvc设计的轻量级Android开发框架。.zip

    Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。

    node-v4.4.7-linux-x86.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v4.2.0-linux-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于SimCity的城市规划(Android).zip

    Android是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的移动操作系统,主要应用于移动设备,如智能手机和平板电脑。该系统最初由安迪·鲁宾开发,后被Google公司收购并注资,随后与多家硬件制造商、软件开发商及电信营运商共同研发改良。 Android操作系统的特点包括: 开放源代码:Android系统采用开放源代码模式,允许开发者自由访问、修改和定制操作系统,这促进了技术的创新和发展,使得Android系统具有高度的灵活性和可定制性。 多任务处理:Android允许用户同时运行多个应用程序,并且可以轻松地在不同应用程序之间切换,提高了效率和便利性。 丰富的应用生态系统:Android系统拥有庞大的应用程序生态系统,用户可以从Google Play商店或其他第三方应用市场下载和安装各种各样的应用程序,满足各种需求。 可定制性:Android操作系统可以根据用户的个人喜好进行定制,用户可以更改主题、小部件和图标等,以使其界面更符合个人风格和偏好。 多种设备支持:Android操作系统可以运行在多种不同类型的设备上,包括手机、平板电脑、智能电视、汽车导航系统等。 此外,Android系统还有一些常见的问题,如应用崩溃、电池耗电过快、Wi-Fi连接问题、存储空间不足、更新问题等。针对这些问题,用户可以尝试一些基本的解决方法,如清除应用缓存和数据、降低屏幕亮度、关闭没有使用的连接和传感器、限制后台运行的应用、删除不需要的文件和应用等。 随着Android系统的不断发展,其功能和性能也在不断提升。例如,最新的Android版本引入了更多的安全性和隐私保护功能,以及更流畅的用户界面和更强大的性能。此外,Android系统也在不断探索新的应用场景,如智能家居、虚拟现实、人工智能等领域。 总之,Android系统是一种功能强大、灵活可定制、拥有丰富应用生态系统的移动操作系统,在全球范围内拥有广泛的用户基础。

    2024-2030中国防水和修复服务市场现状研究分析与发展前景预测报告.docx

    2024-2030中国防水和修复服务市场现状研究分析与发展前景预测报告

    node-v4.3.0-linux-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    37-37.XSS跨站脚本攻击概念介绍.mp4

    37-37.XSS跨站脚本攻击概念介绍.mp4

    node-v4.4.0-sunos-x86.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    51单片机课程设计-温度传感器

    51单片机课程设计-温度传感器

    node-v6.1.0-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v6.14.1-linux-armv7l.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

Global site tag (gtag.js) - Google Analytics