Browse Source

补充部分源码分析,及更新测试例子,后面还继续补充InstanceKeyDataSource和BasicManagedDataSource的测试例子

master
ZhangZiSheng001 6 years ago
parent
commit
a8d5574d38
11 changed files with 21135 additions and 823 deletions
  1. +927
    -369
      README.md
  2. +7779
    -0
      img/dbcp-Connection.cld
  3. +11772
    -0
      img/dbcp-dataSource.cld
  4. +184
    -0
      src/main/java/cn/zzs/dbcp/BasicDataSourceUtil.java
  5. +0
    -136
      src/main/java/cn/zzs/dbcp/JDBCUtil.java
  6. +165
    -81
      src/main/resources/jdbc.properties
  7. +89
    -91
      src/main/resources/log4j.properties
  8. +45
    -0
      src/main/resources/sql/demo_user.sql
  9. +152
    -0
      src/test/java/cn/zzs/dbcp/BasicDataSourceTest.java
  10. +0
    -146
      src/test/java/cn/zzs/dbcp/DBCPTest.java
  11. +22
    -0
      src/test/java/cn/zzs/dbcp/InstanceKeyDataSourceTest.java

+ 927
- 369
README.md
File diff suppressed because it is too large
View File


+ 7779
- 0
img/dbcp-Connection.cld
File diff suppressed because it is too large
View File


+ 11772
- 0
img/dbcp-dataSource.cld
File diff suppressed because it is too large
View File


+ 184
- 0
src/main/java/cn/zzs/dbcp/BasicDataSourceUtil.java View File

@@ -0,0 +1,184 @@
package cn.zzs.dbcp;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSourceFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* @ClassName: BasicDataSourceUtil
* @Description: 用于获取数据库连接对象的工具类。这里使用BasicDataSource获取连接对象,获取到的连接对象可满足一般的数据库操作
* @author: zzs
* @date: 2019年8月31日 下午9:05:08
*/
public class BasicDataSourceUtil {

private static DataSource dataSource;

private static ThreadLocal<Connection> tl = new ThreadLocal<>();

private static final Object obj = new Object();

private static final Log log = LogFactory.getLog(BasicDataSourceUtil.class);

static {
init();
}

/**
*
* @Title: getConnection
* @Description: 获取数据库连接对象的方法,线程安全
* @author: zzs
* @date: 2019年8月31日 下午9:22:29
* @return: Connection
*/
public static Connection getConnection() throws SQLException {
// 从当前线程中获取连接对象
Connection connection = tl.get();
// 判断为空的话,创建连接并绑定到当前线程
if(connection == null) {
synchronized(obj) {
if(tl.get() == null) {
connection = createConnection();
tl.set(connection);
}
}
}
return connection;
}

/**
*
* @Title: release
* @Description: 释放资源
* @author: zzs
* @date: 2019年8月31日 下午9:39:24
* @param conn
* @param statement
* @return: void
*/
public static void release(Connection conn, Statement statement, ResultSet resultSet) {
if(resultSet != null) {
try {
resultSet.close();
} catch(SQLException e) {
log.error("关闭ResultSet对象异常", e);
}
}
if(statement != null) {
try {
statement.close();
} catch(SQLException e) {
log.error("关闭Statement对象异常", e);
}
}
// 注意:这里不关闭连接
if(conn != null) {
try {
conn.close();
tl.remove();
} catch(SQLException e) {
log.error("关闭Connection对象异常", e);
}
}
}

/**
*
* @Title: startTrasaction
* @Description: 开启事务
* @author: zzs
* @date: 2019年11月3日 上午11:03:24
* @return: void
* @throws Exception
*/
public static void startTrasaction() throws SQLException {
getConnection().setAutoCommit(false);
}

/**
*
* @Title: commit
* @Description: 提交事务
* @author: zzs
* @date: 2019年11月3日 上午11:05:54
* @return: void
*/
public static void commit() {
Connection connection = tl.get();
if(connection != null) {
try {
connection.commit();
connection.setAutoCommit(true);
} catch(SQLException e) {
log.error("提交事务失败", e);
}
}
}

/**
*
* @Title: rollback
* @Description: 回滚事务
* @author: zzs
* @date: 2019年11月3日 上午11:08:12
* @return: void
*/
public static void rollback() {
Connection connection = tl.get();
if(connection != null) {
try {
connection.rollback();
connection.setAutoCommit(true);
} catch(SQLException e) {
log.error("回滚事务失败", e);
}
}
}

/**
*
* @Title: createConnection
* @Description: 创建数据库连接
* @author: zzs
* @date: 2019年8月31日 下午9:27:03
* @return: Connection
* @throws SQLException
*/
private static Connection createConnection() throws SQLException {
Connection conn = null;
// 获得连接
conn = dataSource.getConnection();
return conn;
}

/**
* @Title: init
* @Description: 根据指定配置文件创建数据源对象
* @author: zzs
* @date: 2019年9月1日 上午10:53:05
* @return: void
* @throws Exception
*/
private static void init() {
// 导入配置文件
Properties properties = new Properties();
InputStream in = BasicDataSourceUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
properties.load(in);
// 根据配置文件内容获得数据源对象
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch(Exception ex) {
throw new RuntimeException("根据指定配置文件创建数据源出错", ex);
}
}
}

+ 0
- 136
src/main/java/cn/zzs/dbcp/JDBCUtil.java View File

@@ -1,136 +0,0 @@
package cn.zzs.dbcp;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp2.BasicDataSourceFactory;

/**
* @ClassName: JDBCUtil
* @Description: 用于获取数据库连接对象的工具类
* @author: zzs
* @date: 2019年8月31日 下午9:05:08
*/
public class JDBCUtil {
private static DataSource dataSource;
private static ThreadLocal<Connection> tl = new ThreadLocal<>();
private static Object obj = new Object();
static {
init();
}
/**
*
* @Title: getConnection
* @Description: 获取数据库连接对象的方法,线程安全
* @author: zzs
* @date: 2019年8月31日 下午9:22:29
* @return: Connection
*/
public static Connection getConnection(){
//从当前线程中获取连接对象
Connection connection = tl.get();
//判断为空的话,创建连接并绑定到当前线程
if(connection == null) {
synchronized (obj) {
if(tl.get() == null) {
connection = createConnection();
tl.set(connection);
}
}
}
return connection;
}
/**
*
* @Title: release
* @Description: 释放资源
* @author: zzs
* @date: 2019年8月31日 下午9:39:24
* @param conn
* @param statement
* @return: void
*/
public static void release(Connection conn,Statement statement,ResultSet resultSet) {
if(resultSet!=null) {
try {
resultSet.close();
} catch (SQLException e) {
System.err.println("关闭ResultSet对象异常");
e.printStackTrace();
}
}
if(statement != null) {
try {
statement.close();
} catch (SQLException e) {
System.err.println("关闭Statement对象异常");
e.printStackTrace();
}
}
//注意:这里不关闭连接
if(conn!=null) {
try {
//如果连接失效的话,从当前线程的绑定中删除
if(!conn.isValid(3)) {
tl.remove();
}
} catch (SQLException e) {
System.err.println("校验连接有效性");
e.printStackTrace();
}
}
}
/**
*
* @Title: createConnection
* @Description: 创建数据库连接
* @author: zzs
* @date: 2019年8月31日 下午9:27:03
* @return: Connection
*/
private static Connection createConnection(){
Connection conn = null;
//获得连接
try {
conn = dataSource.getConnection();
} catch (SQLException e) {
System.err.println("从数据源获取连接失败");
e.printStackTrace();
}
return conn;
}
/**
* @Title: init
* @Description: 根据指定配置文件创建数据源对象
* @author: zzs
* @date: 2019年9月1日 上午10:53:05
* @return: void
*/
private static void init() {
//导入配置文件
Properties properties = new Properties();
InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");
try {
properties.load(in);
//根据配置文件内容获得数据源对象
dataSource = BasicDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
System.err.println("导入配置文件出错");
e.printStackTrace();
} catch (Exception e) {
System.err.println("根据指定配置文件创建数据源出错");
e.printStackTrace();
}
}
}


+ 165
- 81
src/main/resources/jdbc.properties View File

@@ -1,99 +1,183 @@
#数据库基本配置
#\u6570\u636e\u5e93\u57fa\u672c\u914d\u7f6e
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true
url=jdbc:mysql://localhost:3306/github_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&useSSL=true
username=root
password=root
#-------------连接数据相关参数--------------------------------
#初始化连接:连接池启动时创建的初始化连接数量
#默认为0
#-------------\u8fde\u63a5\u6c60\u6570\u636e\u76f8\u5173\u53c2\u6570--------------------------------
#\u521d\u59cb\u5316\u8fde\u63a5\u6570\u91cf:\u8fde\u63a5\u6c60\u542f\u52a8\u65f6\u521b\u5efa\u7684\u521d\u59cb\u5316\u8fde\u63a5\u6570\u91cf
#\u9ed8\u8ba4\u4e3a0
initialSize=0
#最大活动连接
#连接池在同一时间能够分配的最大活动连接的数量, 如果设置为非正数则表示不限制
#默认为8
maxActive=8
#最大空闲连接
#连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制
#默认为8
#\u6700\u5927\u6d3b\u52a8\u8fde\u63a5\u6570\u91cf:\u8fde\u63a5\u6c60\u5728\u540c\u4e00\u65f6\u95f4\u80fd\u591f\u5206\u914d\u7684\u6700\u5927\u6d3b\u52a8\u8fde\u63a5\u7684\u6570\u91cf, \u5982\u679c\u8bbe\u7f6e\u4e3a\u8d1f\u6570\u5219\u8868\u793a\u4e0d\u9650\u5236
#\u9ed8\u8ba4\u4e3a8
maxTotal=8
#\u6700\u5927\u7a7a\u95f2\u8fde\u63a5:\u8fde\u63a5\u6c60\u4e2d\u5bb9\u8bb8\u4fdd\u6301\u7a7a\u95f2\u72b6\u6001\u7684\u6700\u5927\u8fde\u63a5\u6570\u91cf,\u8d85\u8fc7\u7684\u7a7a\u95f2\u8fde\u63a5\u5c06\u88ab\u91ca\u653e,\u5982\u679c\u8bbe\u7f6e\u4e3a\u8d1f\u6570\u8868\u793a\u4e0d\u9650\u5236
#\u9ed8\u8ba4\u4e3a8
maxIdle=8
#最小空闲连接
#连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建
#默认为0
#\u6700\u5c0f\u7a7a\u95f2\u8fde\u63a5:\u8fde\u63a5\u6c60\u4e2d\u5bb9\u8bb8\u4fdd\u6301\u7a7a\u95f2\u72b6\u6001\u7684\u6700\u5c0f\u8fde\u63a5\u6570\u91cf,\u4f4e\u4e8e\u8fd9\u4e2a\u6570\u91cf\u5c06\u521b\u5efa\u65b0\u7684\u8fde\u63a5,\u5982\u679c\u8bbe\u7f6e\u4e3a0\u5219\u4e0d\u521b\u5efa
#\u6ce8\u610f\uff1atimeBetweenEvictionRunsMillis\u4e3a\u6b63\u6570\u65f6\uff0c\u8fd9\u4e2a\u53c2\u6570\u624d\u80fd\u751f\u6548\u3002
#\u9ed8\u8ba4\u4e3a0
minIdle=0
#最大等待时间
#当没有可用连接时,连接池等待连接被归还的最大时间(以毫秒计数),超过时间则抛出异常,如果设置为-1表示无限等待
#默认无限
maxWait=-1
#-------------事务相关的属性--------------------------------
#连接池创建的连接的默认的auto-commit状态
#默认为true
defaultAutoCommit=false
#连接池创建的连接的默认的read-only状态. 如果没有设置则setReadOnly方法将不会被调用. (某些驱动不支持只读模式,比如:Informix)
#默认值由驱动决定
#defaultReadOnly=false
#连接池创建的连接的默认的TransactionIsolation状态
#可用值为下列之一:NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
#默认值由驱动决定
defaultTransactionIsolation=REPEATABLE_READ
#连接池创建的连接的默认的catalog
#defaultCatalog
#-------------连接检查情况--------------------------------
#SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录
validationQuery= select 1
#指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个.
#注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
#默认为true
#\u6700\u5927\u7b49\u5f85\u65f6\u95f4
#\u5f53\u6ca1\u6709\u53ef\u7528\u8fde\u63a5\u65f6,\u8fde\u63a5\u6c60\u7b49\u5f85\u8fde\u63a5\u88ab\u5f52\u8fd8\u7684\u6700\u5927\u65f6\u95f4(\u4ee5\u6beb\u79d2\u8ba1\u6570),\u8d85\u8fc7\u65f6\u95f4\u5219\u629b\u51fa\u5f02\u5e38,\u5982\u679c\u8bbe\u7f6e\u4e3a<=0\u8868\u793a\u65e0\u9650\u7b49\u5f85
#\u9ed8\u8ba4-1
maxWaitMillis=-1
#-------------\u8fde\u63a5\u68c0\u67e5\u60c5\u51b5--------------------------------
#\u901a\u8fc7SQL\u67e5\u8be2\u68c0\u6d4b\u8fde\u63a5,\u6ce8\u610f\u5fc5\u987b\u8fd4\u56de\u81f3\u5c11\u4e00\u884c\u8bb0\u5f55
#\u9ed8\u8ba4\u4e3a\u7a7a\u3002\u5373\u4f1a\u8c03\u7528Connection\u7684isValid\u548cisClosed\u8fdb\u884c\u68c0\u6d4b
#\u6ce8\u610f\uff1a\u5982\u679c\u662foracle\u6570\u636e\u5e93\u7684\u8bdd\uff0c\u5e94\u8be5\u6539\u4e3aselect 1 from dual
validationQuery=select 1 from dual
#SQL\u68c0\u9a8c\u8d85\u65f6\u65f6\u95f4
validationQueryTimeout=-1
#\u662f\u5426\u4ece\u6c60\u4e2d\u53d6\u51fa\u8fde\u63a5\u524d\u8fdb\u884c\u68c0\u9a8c\u3002
#\u9ed8\u8ba4\u4e3atrue
testOnBorrow=true
#指明是否在归还到池中前进行检验
#注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
#默认为false
#\u662f\u5426\u5728\u5f52\u8fd8\u5230\u6c60\u4e2d\u524d\u8fdb\u884c\u68c0\u9a8c
#\u9ed8\u8ba4\u4e3afalse
testOnReturn=false
#是否开启空闲资源监测。
#注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
#默认为false
testWhileIdle= true
#空闲资源的检测周期(单位为毫秒)。默认-1:不检测。建议设置,周期自行选择。timeBetweenEvictionRunsMillis=30000
#做空闲资源检测时,每次的采样数。默认3。
#可根据自身应用连接数进行微调,如果设置为-1,就是对所有连接做空闲监测。
#\u662f\u5426\u5f00\u542f\u7a7a\u95f2\u8d44\u6e90\u56de\u6536\u5668\u3002
#\u9ed8\u8ba4\u4e3afalse
testWhileIdle=false
#\u7a7a\u95f2\u8d44\u6e90\u7684\u68c0\u6d4b\u5468\u671f(\u5355\u4f4d\u4e3a\u6beb\u79d2)\u3002
#\u9ed8\u8ba4-1\u3002\u5373\u7a7a\u95f2\u8d44\u6e90\u56de\u6536\u5668\u4e0d\u5de5\u4f5c\u3002
timeBetweenEvictionRunsMillis=-1
#\u505a\u7a7a\u95f2\u8d44\u6e90\u56de\u6536\u5668\u65f6\uff0c\u6bcf\u6b21\u7684\u91c7\u6837\u6570\u3002
#\u9ed8\u8ba43\uff0c\u5355\u4f4d\u6beb\u79d2\u3002\u5982\u679c\u8bbe\u7f6e\u4e3a-1\uff0c\u5c31\u662f\u5bf9\u6240\u6709\u8fde\u63a5\u505a\u7a7a\u95f2\u76d1\u6d4b\u3002
numTestsPerEvictionRun=3
#资源池中资源最小空闲时间(单位为毫秒),达到此值后空闲资源将被移除。
#默认值1000*60*30 = 30分钟。建议默认,或根据自身业务选择。
#\u8d44\u6e90\u6c60\u4e2d\u8d44\u6e90\u6700\u5c0f\u7a7a\u95f2\u65f6\u95f4(\u5355\u4f4d\u4e3a\u6beb\u79d2)\uff0c\u8fbe\u5230\u6b64\u503c\u540e\u5c06\u88ab\u79fb\u9664\u3002
#\u9ed8\u8ba4\u503c1000*60*30 = 30\u5206\u949f
minEvictableIdleTimeMillis=1800000
#-------------缓存语句--------------------------------
#开启池的prepared statement 池功能
#注意: 确认连接还有剩余资源可以留给其他statement
#默认为false
#\u8d44\u6e90\u6c60\u4e2d\u8d44\u6e90\u6700\u5c0f\u7a7a\u95f2\u65f6\u95f4(\u5355\u4f4d\u4e3a\u6beb\u79d2)\uff0c\u8fbe\u5230\u6b64\u503c\u540e\u5c06\u88ab\u79fb\u9664\u3002\u4f46\u662f\u4f1a\u4fdd\u8bc1minIdle
#\u9ed8\u8ba4\u503c-1
#softMinEvictableIdleTimeMillis=-1
#\u7a7a\u95f2\u8d44\u6e90\u56de\u6536\u7b56\u7565
#\u9ed8\u8ba4org.apache.commons.pool2.impl.DefaultEvictionPolicy
#\u5982\u679c\u8981\u81ea\u5b9a\u4e49\u7684\u8bdd\uff0c\u9700\u8981\u5b9e\u73b0EvictionPolicy\u91cd\u5199evict\u65b9\u6cd5
evictionPolicyClassName=org.apache.commons.pool2.impl.DefaultEvictionPolicy
#\u8fde\u63a5\u6700\u5927\u5b58\u6d3b\u65f6\u95f4\u3002\u975e\u6b63\u6570\u8868\u793a\u4e0d\u9650\u5236
#\u9ed8\u8ba4-1
maxConnLifetimeMillis=-1
#\u5f53\u8fbe\u5230maxConnLifetimeMillis\u88ab\u5173\u95ed\u65f6\uff0c\u662f\u5426\u6253\u5370\u76f8\u5173\u6d88\u606f
#\u9ed8\u8ba4true
#\u6ce8\u610f\uff1amaxConnLifetimeMillis\u8bbe\u7f6e\u4e3a\u6b63\u6570\u65f6\uff0c\u8fd9\u4e2a\u53c2\u6570\u624d\u6709\u6548
logExpiredConnections=true
#-------------\u7f13\u5b58\u8bed\u53e5--------------------------------
#\u662f\u5426\u7f13\u5b58PreparedStatements\uff0c\u8fd9\u4e2a\u529f\u80fd\u5728\u4e00\u4e9b\u652f\u6301\u6e38\u6807\u7684\u6570\u636e\u5e93\u4e2d\u53ef\u4ee5\u6781\u5927\u63d0\u9ad8\u6027\u80fd\uff08Oracle\u3001SQL Server\u3001DB2\u3001Sybase\uff09
#\u9ed8\u8ba4\u4e3afalse
poolPreparedStatements=false
#statement池能够同时分配的打开的statements的最大数量, 如果设置为0表示不限制
#默认为0
maxOpenPreparedStatements=0
#-------------连接泄漏回收参数--------------------------------
#标记是否删除泄露的连接,如果他们超过了removeAbandonedTimout的限制.
#如果设置为true, 连接被认为是被泄露并且可以被删除,如果空闲时间超过removeAbandonedTimeout.
#设置为true可以为写法糟糕的没有关闭连接的程序修复数据库连接.
#默认为false
removeAbandoned=false
#泄露的连接可以被删除的超时值, 单位秒
#默认为300
#\u7f13\u5b58PreparedStatements\u7684\u6700\u5927\u4e2a\u6570
#\u9ed8\u8ba4\u4e3a-1
#\u6ce8\u610f\uff1apoolPreparedStatements\u4e3atrue\u65f6\uff0c\u8fd9\u4e2a\u53c2\u6570\u624d\u6709\u6548
maxOpenPreparedStatements=-1
#\u7f13\u5b58read-only\u548cauto-commit\u72b6\u6001\u3002\u8bbe\u7f6e\u4e3atrue\u7684\u8bdd\uff0c\u6240\u6709\u8fde\u63a5\u7684\u72b6\u6001\u90fd\u4f1a\u662f\u4e00\u6837\u7684\u3002
#\u9ed8\u8ba4\u662ftrue
cacheState=true
#-------------\u4e8b\u52a1\u76f8\u5173\u7684\u5c5e\u6027--------------------------------
#\u8fde\u63a5\u6c60\u521b\u5efa\u7684\u8fde\u63a5\u7684\u9ed8\u8ba4\u7684auto-commit\u72b6\u6001
#\u9ed8\u8ba4\u4e3a\u7a7a\uff0c\u7531\u9a71\u52a8\u51b3\u5b9a
defaultAutoCommit=true
#\u8fde\u63a5\u6c60\u521b\u5efa\u7684\u8fde\u63a5\u7684\u9ed8\u8ba4\u7684read-only\u72b6\u6001\u3002
#\u9ed8\u8ba4\u503c\u4e3a\u7a7a\uff0c\u7531\u9a71\u52a8\u51b3\u5b9a
defaultReadOnly=false
#\u8fde\u63a5\u6c60\u521b\u5efa\u7684\u8fde\u63a5\u7684\u9ed8\u8ba4\u7684TransactionIsolation\u72b6\u6001
#\u53ef\u7528\u503c\u4e3a\u4e0b\u5217\u4e4b\u4e00\uff1aNONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
#\u9ed8\u8ba4\u503c\u4e3a\u7a7a\uff0c\u7531\u9a71\u52a8\u51b3\u5b9a
defaultTransactionIsolation=REPEATABLE_READ
#\u5f52\u8fd8\u8fde\u63a5\u65f6\u662f\u5426\u8bbe\u7f6e\u81ea\u52a8\u63d0\u4ea4\u4e3atrue
#\u9ed8\u8ba4true
autoCommitOnReturn=true
#\u5f52\u8fd8\u8fde\u63a5\u65f6\u662f\u5426\u8bbe\u7f6e\u56de\u6eda\u4e8b\u52a1
#\u9ed8\u8ba4true
rollbackOnReturn=true
#\u8fde\u63a5\u6c60\u521b\u5efa\u7684\u8fde\u63a5\u7684\u9ed8\u8ba4\u7684\u6570\u636e\u5e93\u540d
#defaultCatalog=github_demo
#\u8fde\u63a5\u6c60\u521b\u5efa\u7684\u8fde\u63a5\u7684\u9ed8\u8ba4\u7684schema\u3002\u5982\u679c\u662fmysql\uff0c\u8fd9\u4e2a\u8bbe\u7f6e\u6ca1\u4ec0\u4e48\u7528\u3002
#defaultSchema=github_demo
#-------------\u8fde\u63a5\u6cc4\u6f0f\u56de\u6536\u53c2\u6570--------------------------------
#\u5f53\u672a\u4f7f\u7528\u7684\u65f6\u95f4\u8d85\u8fc7removeAbandonedTimeout\u65f6\uff0c\u662f\u5426\u89c6\u8be5\u8fde\u63a5\u4e3a\u6cc4\u9732\u8fde\u63a5\u5e76\u5220\u9664\uff08\u5f53getConnection()\u88ab\u8c03\u7528\u65f6\u68c0\u6d4b\uff09
#\u9ed8\u8ba4\u4e3afalse
#\u6ce8\u610f\uff1a\u8fd9\u4e2a\u673a\u5236\u5728(getNumIdle() < 2) and (getNumActive() > (getMaxActive() - 3))\u65f6\u88ab\u89e6\u53d1
removeAbandonedOnBorrow=false
#\u5f53\u672a\u4f7f\u7528\u7684\u65f6\u95f4\u8d85\u8fc7removeAbandonedTimeout\u65f6\uff0c\u662f\u5426\u89c6\u8be5\u8fde\u63a5\u4e3a\u6cc4\u9732\u8fde\u63a5\u5e76\u5220\u9664\uff08\u7a7a\u95f2evictor\u68c0\u6d4b\uff09
#\u9ed8\u8ba4\u4e3afalse
#\u6ce8\u610f\uff1a\u5f53\u7a7a\u95f2\u8d44\u6e90\u56de\u6536\u5668\u5f00\u542f\u624d\u751f\u6548
removeAbandonedOnMaintenance=false
#\u6cc4\u9732\u7684\u8fde\u63a5\u53ef\u4ee5\u88ab\u5220\u9664\u7684\u8d85\u65f6\u503c, \u5355\u4f4d\u79d2
#\u9ed8\u8ba4\u4e3a300
removeAbandonedTimeout=300
#标记当Statement或连接被泄露时是否打印程序的stack traces日志。
#被泄露的Statements和连接的日志添加在每个连接打开或者生成新的Statement,因为需要生成stack trace。
#默认为false
logAbandoned=false
#如果开启"removeAbandoned",那么连接在被认为泄露时可能被池回收.
#这个机制在(getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3)时被触发.
#举例当maxActive=20, 活动连接为18,空闲连接为1时可以触发"removeAbandoned".
#但是活动连接只有在没有被使用的时间超过"removeAbandonedTimeout"时才被删除,默认300秒.在resultset中游历不被计算为被使用.
#-------------其他--------------------------------
#控制PoolGuard是否容许获取底层连接
#默认为false
#\u6807\u8bb0\u5f53Statement\u6216\u8fde\u63a5\u88ab\u6cc4\u9732\u65f6\u662f\u5426\u6253\u5370\u7a0b\u5e8f\u7684stack traces\u65e5\u5fd7\u3002
#\u9ed8\u8ba4\u4e3afalse
logAbandoned=true
#\u8fd9\u4e2a\u4e0d\u662f\u5f88\u61c2
#\u9ed8\u8ba4\u4e3afalse
abandonedUsageTracking=false
#-------------\u5176\u4ed6--------------------------------
#\u662f\u5426\u4f7f\u7528\u5feb\u901f\u5931\u8d25\u673a\u5236
#\u9ed8\u8ba4\u4e3a\u7a7a\uff0c\u7531\u9a71\u52a8\u51b3\u5b9a
fastFailValidation=false
#\u5f53\u4f7f\u7528\u5feb\u901f\u5931\u8d25\u673a\u5236\u65f6\uff0c\u8bbe\u7f6e\u89e6\u53d1\u7684\u5f02\u5e38\u7801
#\u591a\u4e2acode\u7528","\u9694\u5f00
#disconnectionSqlCodes
#borrow\u8fde\u63a5\u7684\u987a\u5e8f
#\u9ed8\u8ba4true
lifo=true
#\u6bcf\u4e2a\u8fde\u63a5\u521b\u5efa\u65f6\u6267\u884c\u7684\u8bed\u53e5
#connectionInitSqls=
#\u8fde\u63a5\u53c2\u6570\uff1a\u4f8b\u5982username\u3001password\u3001characterEncoding\u7b49\u90fd\u53ef\u4ee5\u5728\u8fd9\u91cc\u8bbe\u7f6e
#\u591a\u4e2a\u53c2\u6570\u7528";"\u9694\u5f00
#connectionProperties=
#\u6307\u5b9a\u6570\u636e\u6e90\u7684jmx\u540d
#jmxName=
#\u67e5\u8be2\u8d85\u65f6\u65f6\u95f4
#\u9ed8\u8ba4\u4e3a\u7a7a\uff0c\u5373\u6839\u636e\u9a71\u52a8\u8bbe\u7f6e
#defaultQueryTimeout=
#\u63a7\u5236PoolGuard\u662f\u5426\u5bb9\u8bb8\u83b7\u53d6\u5e95\u5c42\u8fde\u63a5
#\u9ed8\u8ba4\u4e3afalse
accessToUnderlyingConnectionAllowed=false
#如果容许则可以使用下面的方式来获取底层物理连接:
#\u5982\u679c\u5bb9\u8bb8\u5219\u53ef\u4ee5\u4f7f\u7528\u4e0b\u9762\u7684\u65b9\u5f0f\u6765\u83b7\u53d6\u5e95\u5c42\u7269\u7406\u8fde\u63a5:
# Connection conn = ds.getConnection();
# Connection dconn = ((DelegatingConnection) conn).getInnermostDelegate();
# ...

+ 89
- 91
src/main/resources/log4j.properties View File

@@ -1,12 +1,10 @@
#OFF,systemOut,logFile,logDailyFile,logRollingFile,logMail,logDB,ALL
#①配置根Logger
log4j.rootLogger=debug,systemOut
#OFF,systemOut,logFile,logDailyFile,logRollingFile,logMail,logDB,ALL
#②配置其他Logger
#log4j.logger.myLogger=debug,systemOut
#log4j.additivity.mobileLogger=false
#\u2460\u914d\u7f6e\u6839Logger
log4j.rootLogger=info,systemOut
log4j.logger.cn.zzs.dbcp=debug,systemOut
log4j.additivity.cn.zzs.dbcp=false
#输出到控制台
#\u8f93\u51fa\u5230\u63a7\u5236\u53f0
log4j.appender.systemOut= org.apache.log4j.ConsoleAppender
log4j.appender.systemOut.layout= org.apache.log4j.PatternLayout
log4j.appender.systemOut.layout.ConversionPattern=[%p][Thread:%t]: %m%n
@@ -14,7 +12,7 @@ log4j.appender.systemOut.Threshold= debug
log4j.appender.systemOut.ImmediateFlush= TRUE
log4j.appender.systemOut.Target= System.out
#输出到文件
#\u8f93\u51fa\u5230\u6587\u4ef6
log4j.appender.logFile= org.apache.log4j.FileAppender
log4j.appender.logFile.layout= org.apache.log4j.PatternLayout
log4j.appender.logFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread:%t][Class:%c Method: %M]%n%p: %m%n
@@ -24,7 +22,7 @@ log4j.appender.logFile.Append= TRUE
log4j.appender.logFile.File= logs/file_log.log
log4j.appender.logFile.Encoding= utf-8
#按DatePattern输出到文件
#\u6309DatePattern\u8f93\u51fa\u5230\u6587\u4ef6
log4j.appender.logDailyFile= org.apache.log4j.DailyRollingFileAppender
log4j.appender.logDailyFile.layout= org.apache.log4j.PatternLayout
log4j.appender.logDailyFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread:%t][Class:%c Method: %M]%n%p: %m%n
@@ -36,7 +34,7 @@ log4j.appender.logDailyFile.File= logs/daily_log
log4j.appender.logDailyFile.DatePattern= '_'yyyy-MM-dd-HH-mm'.log'
log4j.appender.logDailyFile.Encoding= utf-8
#设定文件大小输出到文件
#\u8bbe\u5b9a\u6587\u4ef6\u5927\u5c0f\u8f93\u51fa\u5230\u6587\u4ef6
log4j.appender.logRollingFile= org.apache.log4j.RollingFileAppender
log4j.appender.logRollingFile.layout= org.apache.log4j.PatternLayout
log4j.appender.logRollingFile.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss a} [Thread:%t][Class:%c Method: %M]%n%p: %m%n
@@ -48,7 +46,7 @@ log4j.appender.logRollingFile.MaxFileSize= 1mb
log4j.appender.logRollingFile.MaxBackupIndex= 10
log4j.appender.logRollingFile.Encoding= utf-8
#用Email发送日志
#\u7528Email\u53d1\u9001\u65e5\u5fd7
log4j.appender.logMail= org.apache.log4j.net.SMTPAppender
log4j.appender.logMail.layout= org.apache.log4j.HTMLLayout
log4j.appender.logMail.layout.LocationInfo= TRUE
@@ -66,7 +64,7 @@ log4j.appender.logMail.Subject= Log4j Log Messages
#log4j.appender.logMail.BufferSize= 1024
#log4j.appender.logMail.SMTPAuth= TRUE
#将日志登录到MySQL数据库
#\u5c06\u65e5\u5fd7\u767b\u5f55\u5230MySQL\u6570\u636e\u5e93
log4j.appender.logDB= org.apache.log4j.jdbc.JDBCAppender
log4j.appender.logDB.layout= org.apache.log4j.PatternLayout
log4j.appender.logDB.Driver= com.mysql.cj.jdbc.Driver
@@ -75,109 +73,109 @@ log4j.appender.logDB.User= root
log4j.appender.logDB.Password= root
log4j.appender.logDB.Sql= INSERT INTO T_log4j(project_name,create_date,level,category,file_name,thread_name,line,all_category,message)values('Struts2','%d{yyyy-MM-ddHH:mm:ss}','%p','%c','%F','%t','%L','%l','%m')
################################################################################
#①配置根Logger,其语法为:
#\u2460\u914d\u7f6e\u6839Logger\uff0c\u5176\u8bed\u6cd5\u4e3a\uff1a
#
#log4j.rootLogger =[level],appenderName,appenderName2,...
#level是日志记录的优先级,分为OFF,TRACE,DEBUG,INFO,WARN,ERROR,FATAL,ALL
##Log4j建议只使用四个级别,优先级从低到高分别是DEBUG,INFO,WARN,ERROR
#通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关
#比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来
#appenderName就是指定日志信息输出到哪个地方。可同时指定多个输出目的
#level\u662f\u65e5\u5fd7\u8bb0\u5f55\u7684\u4f18\u5148\u7ea7\uff0c\u5206\u4e3aOFF,TRACE,DEBUG,INFO,WARN,ERROR,FATAL,ALL
##Log4j\u5efa\u8bae\u53ea\u4f7f\u7528\u56db\u4e2a\u7ea7\u522b\uff0c\u4f18\u5148\u7ea7\u4ece\u4f4e\u5230\u9ad8\u5206\u522b\u662fDEBUG,INFO,WARN,ERROR
#\u901a\u8fc7\u5728\u8fd9\u91cc\u5b9a\u4e49\u7684\u7ea7\u522b\uff0c\u60a8\u53ef\u4ee5\u63a7\u5236\u5230\u5e94\u7528\u7a0b\u5e8f\u4e2d\u76f8\u5e94\u7ea7\u522b\u7684\u65e5\u5fd7\u4fe1\u606f\u7684\u5f00\u5173
#\u6bd4\u5982\u5728\u8fd9\u91cc\u5b9a\u4e49\u4e86INFO\u7ea7\u522b\uff0c\u5219\u5e94\u7528\u7a0b\u5e8f\u4e2d\u6240\u6709DEBUG\u7ea7\u522b\u7684\u65e5\u5fd7\u4fe1\u606f\u5c06\u4e0d\u88ab\u6253\u5370\u51fa\u6765
#appenderName\u5c31\u662f\u6307\u5b9a\u65e5\u5fd7\u4fe1\u606f\u8f93\u51fa\u5230\u54ea\u4e2a\u5730\u65b9\u3002\u53ef\u540c\u65f6\u6307\u5b9a\u591a\u4e2a\u8f93\u51fa\u76ee\u7684
################################################################################
################################################################################
#②配置日志信息输出目的地Appender,其语法为:
#\u2461\u914d\u7f6e\u65e5\u5fd7\u4fe1\u606f\u8f93\u51fa\u76ee\u7684\u5730Appender\uff0c\u5176\u8bed\u6cd5\u4e3a\uff1a
#
#log4j.appender.appenderName =fully.qualified.name.of.appender.class
#log4j.appender.appenderName.optionN =valueN
#
#Log4j提供的appender有以下几种:
#1)org.apache.log4j.ConsoleAppender(输出到控制台)
#2)org.apache.log4j.FileAppender(输出到文件)
#3)org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
#4)org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
#5)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
#Log4j\u63d0\u4f9b\u7684appender\u6709\u4ee5\u4e0b\u51e0\u79cd\uff1a
#1)org.apache.log4j.ConsoleAppender(\u8f93\u51fa\u5230\u63a7\u5236\u53f0)
#2)org.apache.log4j.FileAppender(\u8f93\u51fa\u5230\u6587\u4ef6)
#3)org.apache.log4j.DailyRollingFileAppender(\u6bcf\u5929\u4ea7\u751f\u4e00\u4e2a\u65e5\u5fd7\u6587\u4ef6)
#4)org.apache.log4j.RollingFileAppender(\u6587\u4ef6\u5927\u5c0f\u5230\u8fbe\u6307\u5b9a\u5c3a\u5bf8\u7684\u65f6\u5019\u4ea7\u751f\u4e00\u4e2a\u65b0\u7684\u6587\u4ef6)
#5)org.apache.log4j.WriterAppender(\u5c06\u65e5\u5fd7\u4fe1\u606f\u4ee5\u6d41\u683c\u5f0f\u53d1\u9001\u5230\u4efb\u610f\u6307\u5b9a\u7684\u5730\u65b9)
#
#1)ConsoleAppender选项属性
# -Threshold = DEBUG:指定日志消息的输出最低层次
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
# -Target = System.err:默认值System.out,输出到控制台(err为红色,out为黑色)
#1)ConsoleAppender\u9009\u9879\u5c5e\u6027
# -Threshold = DEBUG:\u6307\u5b9a\u65e5\u5fd7\u6d88\u606f\u7684\u8f93\u51fa\u6700\u4f4e\u5c42\u6b21
# -ImmediateFlush = TRUE:\u9ed8\u8ba4\u503c\u662ftrue,\u6240\u6709\u7684\u6d88\u606f\u90fd\u4f1a\u88ab\u7acb\u5373\u8f93\u51fa
# -Target = System.err:\u9ed8\u8ba4\u503cSystem.out,\u8f93\u51fa\u5230\u63a7\u5236\u53f0(err\u4e3a\u7ea2\u8272,out\u4e3a\u9ed1\u8272)
#
#2)FileAppender选项属性
# -Threshold = INFO:指定日志消息的输出最低层次
# -ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
# -File = C:\log4j.log:指定消息输出到C:\log4j.log文件
# -Append = FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容
# -Encoding = UTF-8:可以指定文件编码格式
#2)FileAppender\u9009\u9879\u5c5e\u6027
# -Threshold = INFO:\u6307\u5b9a\u65e5\u5fd7\u6d88\u606f\u7684\u8f93\u51fa\u6700\u4f4e\u5c42\u6b21
# -ImmediateFlush = TRUE:\u9ed8\u8ba4\u503c\u662ftrue,\u6240\u6709\u7684\u6d88\u606f\u90fd\u4f1a\u88ab\u7acb\u5373\u8f93\u51fa
# -File = C:\log4j.log:\u6307\u5b9a\u6d88\u606f\u8f93\u51fa\u5230C:\log4j.log\u6587\u4ef6
# -Append = FALSE:\u9ed8\u8ba4\u503ctrue,\u5c06\u6d88\u606f\u8ffd\u52a0\u5230\u6307\u5b9a\u6587\u4ef6\u4e2d\uff0cfalse\u6307\u5c06\u6d88\u606f\u8986\u76d6\u6307\u5b9a\u7684\u6587\u4ef6\u5185\u5bb9
# -Encoding = UTF-8:\u53ef\u4ee5\u6307\u5b9a\u6587\u4ef6\u7f16\u7801\u683c\u5f0f
#
#3)DailyRollingFileAppender选项属性
#-Threshold = WARN:指定日志消息的输出最低层次
#-ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
# -File =C:\log4j.log:指定消息输出到C:\log4j.log文件
# -Append= FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容
#-DatePattern='.'yyyy-ww:每周滚动一次文件,即每周产生一个新的文件。还可以按用以下参数:
# '.'yyyy-MM:每月
# '.'yyyy-ww:每周
# '.'yyyy-MM-dd:每天
# '.'yyyy-MM-dd-a:每天两次
# '.'yyyy-MM-dd-HH:每小时
# '.'yyyy-MM-dd-HH-mm:每分钟
#-Encoding = UTF-8:可以指定文件编码格式
#3)DailyRollingFileAppender\u9009\u9879\u5c5e\u6027
#-Threshold = WARN:\u6307\u5b9a\u65e5\u5fd7\u6d88\u606f\u7684\u8f93\u51fa\u6700\u4f4e\u5c42\u6b21
#-ImmediateFlush = TRUE:\u9ed8\u8ba4\u503c\u662ftrue,\u6240\u6709\u7684\u6d88\u606f\u90fd\u4f1a\u88ab\u7acb\u5373\u8f93\u51fa
# -File =C:\log4j.log:\u6307\u5b9a\u6d88\u606f\u8f93\u51fa\u5230C:\log4j.log\u6587\u4ef6
# -Append= FALSE:\u9ed8\u8ba4\u503ctrue,\u5c06\u6d88\u606f\u8ffd\u52a0\u5230\u6307\u5b9a\u6587\u4ef6\u4e2d\uff0cfalse\u6307\u5c06\u6d88\u606f\u8986\u76d6\u6307\u5b9a\u7684\u6587\u4ef6\u5185\u5bb9
#-DatePattern='.'yyyy-ww:\u6bcf\u5468\u6eda\u52a8\u4e00\u6b21\u6587\u4ef6,\u5373\u6bcf\u5468\u4ea7\u751f\u4e00\u4e2a\u65b0\u7684\u6587\u4ef6\u3002\u8fd8\u53ef\u4ee5\u6309\u7528\u4ee5\u4e0b\u53c2\u6570:
# '.'yyyy-MM:\u6bcf\u6708
# '.'yyyy-ww:\u6bcf\u5468
# '.'yyyy-MM-dd:\u6bcf\u5929
# '.'yyyy-MM-dd-a:\u6bcf\u5929\u4e24\u6b21
# '.'yyyy-MM-dd-HH:\u6bcf\u5c0f\u65f6
# '.'yyyy-MM-dd-HH-mm:\u6bcf\u5206\u949f
#-Encoding = UTF-8:\u53ef\u4ee5\u6307\u5b9a\u6587\u4ef6\u7f16\u7801\u683c\u5f0f
#
#4)RollingFileAppender选项属性
#-Threshold = ERROR:指定日志消息的输出最低层次
#-ImmediateFlush = TRUE:默认值是true,所有的消息都会被立即输出
# -File =C:/log4j.log:指定消息输出到C:/log4j.log文件
# -Append= FALSE:默认值true,将消息追加到指定文件中,false指将消息覆盖指定的文件内容
#-MaxFileSize = 100KB:后缀可以是KB,MB,GB.在日志文件到达该大小时,将会自动滚动.如:log4j.log.1
#-MaxBackupIndex = 2:指定可以产生的滚动文件的最大数
#-Encoding = UTF-8:可以指定文件编码格式
#4)RollingFileAppender\u9009\u9879\u5c5e\u6027
#-Threshold = ERROR:\u6307\u5b9a\u65e5\u5fd7\u6d88\u606f\u7684\u8f93\u51fa\u6700\u4f4e\u5c42\u6b21
#-ImmediateFlush = TRUE:\u9ed8\u8ba4\u503c\u662ftrue,\u6240\u6709\u7684\u6d88\u606f\u90fd\u4f1a\u88ab\u7acb\u5373\u8f93\u51fa
# -File =C:/log4j.log:\u6307\u5b9a\u6d88\u606f\u8f93\u51fa\u5230C:/log4j.log\u6587\u4ef6
# -Append= FALSE:\u9ed8\u8ba4\u503ctrue,\u5c06\u6d88\u606f\u8ffd\u52a0\u5230\u6307\u5b9a\u6587\u4ef6\u4e2d\uff0cfalse\u6307\u5c06\u6d88\u606f\u8986\u76d6\u6307\u5b9a\u7684\u6587\u4ef6\u5185\u5bb9
#-MaxFileSize = 100KB:\u540e\u7f00\u53ef\u4ee5\u662fKB,MB,GB.\u5728\u65e5\u5fd7\u6587\u4ef6\u5230\u8fbe\u8be5\u5927\u5c0f\u65f6,\u5c06\u4f1a\u81ea\u52a8\u6eda\u52a8.\u5982:log4j.log.1
#-MaxBackupIndex = 2:\u6307\u5b9a\u53ef\u4ee5\u4ea7\u751f\u7684\u6eda\u52a8\u6587\u4ef6\u7684\u6700\u5927\u6570
#-Encoding = UTF-8:\u53ef\u4ee5\u6307\u5b9a\u6587\u4ef6\u7f16\u7801\u683c\u5f0f
################################################################################
################################################################################
#③配置日志信息的格式(布局),其语法为:
#\u2462\u914d\u7f6e\u65e5\u5fd7\u4fe1\u606f\u7684\u683c\u5f0f(\u5e03\u5c40)\uff0c\u5176\u8bed\u6cd5\u4e3a\uff1a
#
#log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
#log4j.appender.appenderName.layout.optionN= valueN
#
#Log4j提供的layout有以下几种:
#5)org.apache.log4j.HTMLLayout(以HTML表格形式布局)
#6)org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
#7)org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
#8)org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
#9)org.apache.log4j.xml.XMLLayout(以XML形式布局)
#Log4j\u63d0\u4f9b\u7684layout\u6709\u4ee5\u4e0b\u51e0\u79cd\uff1a
#5)org.apache.log4j.HTMLLayout(\u4ee5HTML\u8868\u683c\u5f62\u5f0f\u5e03\u5c40)
#6)org.apache.log4j.PatternLayout(\u53ef\u4ee5\u7075\u6d3b\u5730\u6307\u5b9a\u5e03\u5c40\u6a21\u5f0f)
#7)org.apache.log4j.SimpleLayout(\u5305\u542b\u65e5\u5fd7\u4fe1\u606f\u7684\u7ea7\u522b\u548c\u4fe1\u606f\u5b57\u7b26\u4e32)
#8)org.apache.log4j.TTCCLayout(\u5305\u542b\u65e5\u5fd7\u4ea7\u751f\u7684\u65f6\u95f4\u3001\u7ebf\u7a0b\u3001\u7c7b\u522b\u7b49\u7b49\u4fe1\u606f)
#9)org.apache.log4j.xml.XMLLayout(\u4ee5XML\u5f62\u5f0f\u5e03\u5c40)
#
#5)HTMLLayout选项属性
#-LocationInfo = TRUE:默认值false,输出java文件名称和行号
#-Title=Struts Log Message:默认值 Log4JLog Messages
#5)HTMLLayout\u9009\u9879\u5c5e\u6027
#-LocationInfo = TRUE:\u9ed8\u8ba4\u503cfalse,\u8f93\u51fajava\u6587\u4ef6\u540d\u79f0\u548c\u884c\u53f7
#-Title=Struts Log Message:\u9ed8\u8ba4\u503c Log4JLog Messages
#
#6)PatternLayout选项属性
#-ConversionPattern = %m%n:格式化指定的消息(参数意思下面有)
#6)PatternLayout\u9009\u9879\u5c5e\u6027
#-ConversionPattern = %m%n:\u683c\u5f0f\u5316\u6307\u5b9a\u7684\u6d88\u606f(\u53c2\u6570\u610f\u601d\u4e0b\u9762\u6709)
#
#9)XMLLayout选项属性
#-LocationInfo = TRUE:默认值false,输出java文件名称和行号
#9)XMLLayout\u9009\u9879\u5c5e\u6027
#-LocationInfo = TRUE:\u9ed8\u8ba4\u503cfalse,\u8f93\u51fajava\u6587\u4ef6\u540d\u79f0\u548c\u884c\u53f7
#
#Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下:
#%m 输出代码中指定的消息
#%p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
#%r 输出自应用启动到输出该log信息耗费的毫秒数
#%c 输出所属的类目,通常就是所在类的全名
#%t 输出产生该日志事件的线程名
#%n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
#%d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式
# 如:%d{yyyy年MM月dd日HH:mm:ss,SSS},输出类似:2012年01月05日 22:10:28,921
#%l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数
# 如:Testlog.main(TestLog.java:10)
#%F 输出日志消息产生时所在的文件名称
#%L 输出代码中的行号
#%x 输出和当前线程相关联的NDC(嵌套诊断环境),像javaservlets多客户多线程的应用中
#%% 输出一个"%"字符
#Log4J\u91c7\u7528\u7c7b\u4f3cC\u8bed\u8a00\u4e2d\u7684printf\u51fd\u6570\u7684\u6253\u5370\u683c\u5f0f\u683c\u5f0f\u5316\u65e5\u5fd7\u4fe1\u606f\uff0c\u6253\u5370\u53c2\u6570\u5982\u4e0b\uff1a
#%m \u8f93\u51fa\u4ee3\u7801\u4e2d\u6307\u5b9a\u7684\u6d88\u606f
#%p \u8f93\u51fa\u4f18\u5148\u7ea7\uff0c\u5373DEBUG,INFO,WARN,ERROR,FATAL
#%r \u8f93\u51fa\u81ea\u5e94\u7528\u542f\u52a8\u5230\u8f93\u51fa\u8be5log\u4fe1\u606f\u8017\u8d39\u7684\u6beb\u79d2\u6570
#%c \u8f93\u51fa\u6240\u5c5e\u7684\u7c7b\u76ee,\u901a\u5e38\u5c31\u662f\u6240\u5728\u7c7b\u7684\u5168\u540d
#%t \u8f93\u51fa\u4ea7\u751f\u8be5\u65e5\u5fd7\u4e8b\u4ef6\u7684\u7ebf\u7a0b\u540d
#%n \u8f93\u51fa\u4e00\u4e2a\u56de\u8f66\u6362\u884c\u7b26\uff0cWindows\u5e73\u53f0\u4e3a\u201c\r\n\u201d\uff0cUnix\u5e73\u53f0\u4e3a\u201c\n\u201d
#%d \u8f93\u51fa\u65e5\u5fd7\u65f6\u95f4\u70b9\u7684\u65e5\u671f\u6216\u65f6\u95f4\uff0c\u9ed8\u8ba4\u683c\u5f0f\u4e3aISO8601\uff0c\u4e5f\u53ef\u4ee5\u5728\u5176\u540e\u6307\u5b9a\u683c\u5f0f
# \u5982\uff1a%d{yyyy\u5e74MM\u6708dd\u65e5HH:mm:ss,SSS}\uff0c\u8f93\u51fa\u7c7b\u4f3c\uff1a2012\u5e7401\u670805\u65e5 22:10:28,921
#%l \u8f93\u51fa\u65e5\u5fd7\u4e8b\u4ef6\u7684\u53d1\u751f\u4f4d\u7f6e\uff0c\u5305\u62ec\u7c7b\u76ee\u540d\u3001\u53d1\u751f\u7684\u7ebf\u7a0b\uff0c\u4ee5\u53ca\u5728\u4ee3\u7801\u4e2d\u7684\u884c\u6570
# \u5982\uff1aTestlog.main(TestLog.java:10)
#%F \u8f93\u51fa\u65e5\u5fd7\u6d88\u606f\u4ea7\u751f\u65f6\u6240\u5728\u7684\u6587\u4ef6\u540d\u79f0
#%L \u8f93\u51fa\u4ee3\u7801\u4e2d\u7684\u884c\u53f7
#%x \u8f93\u51fa\u548c\u5f53\u524d\u7ebf\u7a0b\u76f8\u5173\u8054\u7684NDC(\u5d4c\u5957\u8bca\u65ad\u73af\u5883),\u50cfjavaservlets\u591a\u5ba2\u6237\u591a\u7ebf\u7a0b\u7684\u5e94\u7528\u4e2d
#%% \u8f93\u51fa\u4e00\u4e2a"%"\u5b57\u7b26
#
# 可以在%与模式字符之间加上修饰符来控制其最小宽度、最大宽度、和文本的对齐方式。如:
# %5c: 输出category名称,最小宽度是5,category<5,默认的情况下右对齐
# %-5c:输出category名称,最小宽度是5,category<5,"-"号指定左对齐,会有空格
# %.5c:输出category名称,最大宽度是5,category>5,就会将左边多出的字符截掉,<5不会有空格
# %20.30c:category名称<20补空格,并且右对齐,>30字符,就从左边交远销出的字符截掉
# \u53ef\u4ee5\u5728%\u4e0e\u6a21\u5f0f\u5b57\u7b26\u4e4b\u95f4\u52a0\u4e0a\u4fee\u9970\u7b26\u6765\u63a7\u5236\u5176\u6700\u5c0f\u5bbd\u5ea6\u3001\u6700\u5927\u5bbd\u5ea6\u3001\u548c\u6587\u672c\u7684\u5bf9\u9f50\u65b9\u5f0f\u3002\u5982\uff1a
# %5c: \u8f93\u51facategory\u540d\u79f0\uff0c\u6700\u5c0f\u5bbd\u5ea6\u662f5\uff0ccategory<5\uff0c\u9ed8\u8ba4\u7684\u60c5\u51b5\u4e0b\u53f3\u5bf9\u9f50
# %-5c:\u8f93\u51facategory\u540d\u79f0\uff0c\u6700\u5c0f\u5bbd\u5ea6\u662f5\uff0ccategory<5\uff0c"-"\u53f7\u6307\u5b9a\u5de6\u5bf9\u9f50,\u4f1a\u6709\u7a7a\u683c
# %.5c:\u8f93\u51facategory\u540d\u79f0\uff0c\u6700\u5927\u5bbd\u5ea6\u662f5\uff0ccategory>5\uff0c\u5c31\u4f1a\u5c06\u5de6\u8fb9\u591a\u51fa\u7684\u5b57\u7b26\u622a\u6389\uff0c<5\u4e0d\u4f1a\u6709\u7a7a\u683c
# %20.30c:category\u540d\u79f0<20\u8865\u7a7a\u683c\uff0c\u5e76\u4e14\u53f3\u5bf9\u9f50\uff0c>30\u5b57\u7b26\uff0c\u5c31\u4ece\u5de6\u8fb9\u4ea4\u8fdc\u9500\u51fa\u7684\u5b57\u7b26\u622a\u6389
################################################################################
################################################################################
#④指定特定包的输出特定的级别
#\u2463\u6307\u5b9a\u7279\u5b9a\u5305\u7684\u8f93\u51fa\u7279\u5b9a\u7684\u7ea7\u522b
#log4j.logger.org.springframework=DEBUG
################################################################################

+ 45
- 0
src/main/resources/sql/demo_user.sql View File

@@ -0,0 +1,45 @@

CREATE DATABASE `github_demo` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

USE `github_demo`;

DROP TABLE IF EXISTS `demo_user`;

CREATE TABLE `demo_user` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户id',
`name` varchar(16) COLLATE utf8_unicode_ci NOT NULL COMMENT '用户名',
`age` int(3) unsigned DEFAULT NULL COMMENT '用户年龄',
`gmt_create` datetime DEFAULT NULL COMMENT '记录创建时间',
`gmt_modified` datetime DEFAULT NULL COMMENT '记录最近修改时间',
`deleted` bit(1) DEFAULT b'0' COMMENT '是否删除',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_name` (`name`),
KEY `index_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;


insert into `demo_user`(
`id`, `name`, `age`, `gmt_create`,
`gmt_modified`, `deleted`
)
values
(
1, 'zzs001', 18, '2019-10-01 11:13:42',
'2019-11-01 11:13:50', '\0'
),
(
2, 'zzs002', 18, '2019-11-23 00:00:00',
'2019-11-23 00:00:00', '\0'
),
(
3, 'zzs003', 25, '2019-11-01 11:14:36',
'2019-11-03 00:00:00', '\0'
),
(
4, 'zzf001', 26, '2019-11-04 11:14:51',
'2019-11-03 00:00:00', '\0'
),
(
5, 'zzf002', 17, '2019-11-03 00:00:00',
'2019-11-03 00:00:00', '\0'
);

+ 152
- 0
src/test/java/cn/zzs/dbcp/BasicDataSourceTest.java View File

@@ -0,0 +1,152 @@
package cn.zzs.dbcp;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;

/**
* @ClassName: BasicDataSourceTest
* @Description: 测试使用BasicDataSource获取连接并操作数据库
* @author: zzs
* @date: 2019年8月31日 下午9:39:54
*/
public class BasicDataSourceTest {

private static final Log log = LogFactory.getLog(BasicDataSourceTest.class);

/**
* 测试添加用户
*/
@Test
public void save() {
// 创建sql
String sql = "insert into demo_user values(null,?,?,?,?,?)";
Connection connection = null;
PreparedStatement statement = null;
try {
// 获得连接
connection = BasicDataSourceUtil.getConnection();
// 开启事务设置非自动提交
BasicDataSourceUtil.startTrasaction();
// 获得Statement对象
statement = connection.prepareStatement(sql);
// 设置参数
statement.setString(1, "zzf003");
statement.setInt(2, 18);
statement.setDate(3, new Date(System.currentTimeMillis()));
statement.setDate(4, new Date(System.currentTimeMillis()));
statement.setBoolean(5, false);
// 执行
statement.executeUpdate();
// 提交事务
BasicDataSourceUtil.commit();
} catch(Exception e) {
BasicDataSourceUtil.rollback();
log.error("保存用户失败", e);
} finally {
// 释放资源
BasicDataSourceUtil.release(connection, statement, null);
}
}

/**
* 测试更新用户
*/
@Test
public void update() {
// 创建sql
String sql = "update demo_user set age = ?,gmt_modified = ? where name = ?";
Connection connection = null;
PreparedStatement statement = null;
try {
// 获得连接
connection = BasicDataSourceUtil.getConnection();
// 开启事务
BasicDataSourceUtil.startTrasaction();
// 获得Statement对象
statement = connection.prepareStatement(sql);
// 设置参数
statement.setInt(1, 19);
statement.setDate(2, new Date(System.currentTimeMillis()));
statement.setString(3, "zzf003");
// 执行
statement.executeUpdate();
// 提交事务
BasicDataSourceUtil.commit();
} catch(Exception e) {
log.error("异常导致操作回滚", e);
BasicDataSourceUtil.rollback();
} finally {
// 释放资源
BasicDataSourceUtil.release(connection, statement, null);
}
}

/**
* 测试查找用户
*/
@Test
public void findAll() {
// 创建sql
String sql = "select * from demo_user where deleted = false";
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
// 获得连接
connection = BasicDataSourceUtil.getConnection();
// 获得Statement对象
statement = connection.prepareStatement(sql);
// 执行
resultSet = statement.executeQuery();
// 遍历结果集
while(resultSet.next()) {
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
System.out.println("用户名:" + name + ",年龄:" + age);
}
} catch(SQLException e) {
log.error("查询用户异常", e);
} finally {
// 释放资源
BasicDataSourceUtil.release(connection, statement, resultSet);
}
}

/**
* 测试删除用户
*/
@Test
public void delete() throws Exception {
// 创建sql
String sql = "delete from demo_user where name = ?";
Connection connection = null;
PreparedStatement statement = null;
try {
// 获得连接
connection = BasicDataSourceUtil.getConnection();
// 设置非自动提交
BasicDataSourceUtil.startTrasaction();
// 获得Statement对象
statement = connection.prepareStatement(sql);
// 设置参数
statement.setString(1, "zzf003");
// 执行
statement.executeUpdate();
// 提交事务
BasicDataSourceUtil.commit();
} catch(Exception e) {
log.error("异常导致操作回滚", e);
BasicDataSourceUtil.rollback();
} finally {
// 释放资源
BasicDataSourceUtil.release(connection, statement, null);
}
}
}

+ 0
- 146
src/test/java/cn/zzs/dbcp/DBCPTest.java View File

@@ -1,146 +0,0 @@
package cn.zzs.dbcp;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.junit.Test;
/**
* @ClassName: DBCPTest
* @Description: 测试DBCP
* @author: zzs
* @date: 2019年8月31日 下午9:39:54
*/
public class DBCPTest {
/**
* 测试添加用户
* @throws SQLException
*/
@Test
public void saveUser() throws Exception {
//创建sql
String sql = "insert into user values(null,?,?,?,?)";
//获得连接
Connection connection = JDBCUtil.getConnection();
PreparedStatement statement = null;
try {
//设置非自动提交
connection.setAutoCommit(false);
//获得Statement对象
statement = connection.prepareStatement(sql);
//设置参数
statement.setString(1, "zzs001");
statement.setInt(2, 18);
statement.setDate(3, new Date(System.currentTimeMillis()));
statement.setDate(4, new Date(System.currentTimeMillis()));
//执行
statement.executeUpdate();
//提交事务
connection.commit();
} catch (Exception e) {
System.out.println("异常导致操作回滚");
connection.rollback();
e.printStackTrace();
} finally {
//释放资源
JDBCUtil.release(connection, statement,null);
}
}
/**
* 测试更新用户
*/
@Test
public void updateUser() throws Exception {
//创建sql
String sql = "update user set age = ?,gmt_modified = ? where name = ?";
//获得连接
Connection connection = JDBCUtil.getConnection();
PreparedStatement statement = null;
try {
//设置非自动提交
connection.setAutoCommit(false);
//获得Statement对象
statement = connection.prepareStatement(sql);
//设置参数
statement.setInt(1, 19);
statement.setDate(2, new Date(System.currentTimeMillis()));
statement.setString(3, "zzs001");
//执行
statement.executeUpdate();
//提交事务
connection.commit();
} catch (Exception e) {
System.out.println("异常导致操作回滚");
connection.rollback();
e.printStackTrace();
} finally {
//释放资源
JDBCUtil.release(connection, statement,null);
}
}
/**
* 测试查找用户
*/
@Test
public void findUser() throws Exception {
//创建sql
String sql = "select * from user where name = ?";
//获得连接
Connection connection = JDBCUtil.getConnection();
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
//获得Statement对象
statement = connection.prepareStatement(sql);
//设置参数
statement.setString(1, "zzs001");
//执行
resultSet = statement.executeQuery();
//遍历结果集
while (resultSet.next()) {
String name = resultSet.getString(2);
int age = resultSet.getInt(3);
System.out.println("用户名:" + name + ",年龄:" + age);
}
} finally {
//释放资源
JDBCUtil.release(connection, statement,resultSet);
}
}
/**
* 测试删除用户
*/
@Test
public void deleteUser() throws Exception {
//创建sql
String sql = "delete from user where name = ?";
//获得连接
Connection connection = JDBCUtil.getConnection();
PreparedStatement statement = null;
try {
//设置非自动提交
connection.setAutoCommit(false);
//获得Statement对象
statement = connection.prepareStatement(sql);
//设置参数
statement.setString(1, "zzs001");
//执行
statement.executeUpdate();
//提交事务
connection.commit();
} catch (Exception e) {
System.out.println("异常导致操作回滚");
connection.rollback();
e.printStackTrace();
} finally {
//释放资源
JDBCUtil.release(connection, statement,null);
}
}
}

+ 22
- 0
src/test/java/cn/zzs/dbcp/InstanceKeyDataSourceTest.java View File

@@ -0,0 +1,22 @@
/**
* Copyright © 2019 zzs. All rights reserved.
*
* @Title: InstanceKeyDataSourceTest.java
* @Prject: DBCP-demo
* @Package: cn.zzs.dbcp
* @Description: TODO
* @author: zzs
* @date: 2019年11月27日 上午8:33:40
* @version: V 1.0.0
*/
package cn.zzs.dbcp;

/**
* @ClassName: InstanceKeyDataSourceTest
* @Description: 测试使用SharedPoolDataSource和PerUserPoolDataSource获取连接,并对比二者差异
* @author: zzs
* @date: 2019年11月27日 上午8:33:40
*/
public class InstanceKeyDataSourceTest {
}

Loading…
Cancel
Save