所属文章:池化技术(一)Druid是如何管理数据库连接的?

本代码段对应流程1.3,连接可用性测试:


//数据库连接可用性测试
protected boolean testConnectionInternal(DruidConnectionHolder holder, Connection conn) {
String sqlFile = JdbcSqlStat.getContextSqlFile();
String sqlName = JdbcSqlStat.getContextSqlName(); if (sqlFile != null) {
JdbcSqlStat.setContextSqlFile(null);
}
if (sqlName != null) {
JdbcSqlStat.setContextSqlName(null);
}
try {
if (validConnectionChecker != null) { //checker不为空
//checker是init(主流程2)里通过驱动进行适配的检测者,因为本篇文章基于mysql,所以假设这里适配到的checker是MySqlValidConnectionChecker类型的
boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
long currentTimeMillis = System.currentTimeMillis();
if (holder != null) {
holder.lastValidTimeMillis = currentTimeMillis;
} if (valid && isMySql) {
//这里在现有驱动版本的情况下拿到的lastPacketReceivedTimeMs始终小于0,因为找不到com.mysql.jdbc.MySQLConnection
long lastPacketReceivedTimeMs = MySqlUtils.getLastPacketReceivedTimeMs(conn);
if (lastPacketReceivedTimeMs > 0) {
long mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs;
if (lastPacketReceivedTimeMs > 0 //
&& mysqlIdleMillis >= timeBetweenEvictionRunsMillis) {
discardConnection(conn);
String errorMsg = "discard long time none received connection. "
+ ", jdbcUrl : " + jdbcUrl
+ ", jdbcUrl : " + jdbcUrl
+ ", lastPacketReceivedIdleMillis : " + mysqlIdleMillis;
LOG.error(errorMsg);
return false;
}
}
} return valid; //返回验证结果
} if (conn.isClosed()) {
return false;
} //checker为空时,就直接利用validationQuery进行常规测试
if (null == validationQuery) {
return true; //validationQuery为空就单纯返回true
} Statement stmt = null;
ResultSet rset = null;
try {
stmt = conn.createStatement();
if (getValidationQueryTimeout() > 0) {
stmt.setQueryTimeout(validationQueryTimeout);
}
rset = stmt.executeQuery(validationQuery);
if (!rset.next()) {
return false; //执行检测语句失败,返回false
}
} finally {
//关闭资源
JdbcUtils.close(rset);
JdbcUtils.close(stmt);
} return true; //验证通过返回true
} catch (Throwable ex) {
// skip
return false;
} finally {
if (sqlFile != null) {
JdbcSqlStat.setContextSqlFile(sqlFile);
}
if (sqlName != null) {
JdbcSqlStat.setContextSqlName(sqlName);
}
}
} //MySqlValidConnectionChecker类里的验证方法
public boolean isValidConnection(Connection conn, String validateQuery, int validationQueryTimeout) throws Exception {
if (conn.isClosed()) {
return false;
} if (usePingMethod) { //是否启用ping方法(如果驱动程序有该方法,则这里为true,一般情况下都是true)
if (conn instanceof DruidPooledConnection) {
conn = ((DruidPooledConnection) conn).getConnection();
} if (conn instanceof ConnectionProxy) {
conn = ((ConnectionProxy) conn).getRawObject();
} if (clazz.isAssignableFrom(conn.getClass())) {
if (validationQueryTimeout < 0) {
validationQueryTimeout = DEFAULT_VALIDATION_QUERY_TIMEOUT;
} try {
//ping对象是初始化时拿到驱动程序的一个Method对象,这里通过invoke触发调用
ping.invoke(conn, true, validationQueryTimeout * 1000);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof SQLException) {
throw (SQLException) cause;
}
throw e; //ping出错抛异常
}
return true; //通过则返回true
}
} //如果不支持ping方式检测,则触发SELECT 1的方式进行检测(一般情况下不会触发,都是上面ping方式)
String query = validateQuery;
if (validateQuery == null || validateQuery.isEmpty()) {
query = DEFAULT_VALIDATION_QUERY;
} Statement stmt = null;
ResultSet rs = null;
try {
stmt = conn.createStatement();
if (validationQueryTimeout > 0) {
stmt.setQueryTimeout(validationQueryTimeout);
}
rs = stmt.executeQuery(query);
return true;
} finally {
JdbcUtils.close(rs);
JdbcUtils.close(stmt);
} }

Druid-代码段-1-4的更多相关文章

  1. WPF自定义RoutedEvent事件代码段

    今天在写东西的时候,发现常用的代码段里没有RoutedEvent的,因此,写了一个代码段,方便以后使用,顺便记录一下,如何做代码段. 1.在项目中新建一个XML文件,将扩展名修改为snippet. 2 ...

  2. JavaScript代码段整理笔记系列(二)

    上篇介绍了15个常用代码段,本篇将把剩余的15个补齐,希望对大家有所帮助!!! 16.检测Shift.Alt.Ctrl键: event.shiftKey; //检测Shift event.altKey ...

  3. 我们为什么要看《超实用的Node.JS代码段》

    不知道自己Node.JS水平如何?看这张图 如果一半以上的你都不会,必须看这本书,一线工程师用代码和功能页面来告诉你每一个技巧点. 都会一点,但不知道如何检验自己,看看本书提供的面试题: 1.     ...

  4. 《超实用的JavaScript代码段》—— 读后总结

    这本书全是代码,从头到尾跟着坐下来确实收获很多.比那些古板的教科书式的理解更多,不过书中并不是每个例子都做了,有的作者封装的太多,觉得看了收获不多,就没细看——比如模块渐变.有空好好学学这段的代码. ...

  5. Visual Studio常用小技巧一:代码段+快捷键+插件=效率

    用了visual studio 5年多,也该给自己做下备忘录了.每次进新的组换新的电脑,安装自己熟悉的环境又得重新配置,不做些备忘老会忘记一些东西.工具用的好,效率自然翻倍. 1,代码段 在Visua ...

  6. 使用eclipse开发Morphline的Java代码段

    背景:morphline是一个轻量级的etl工具.除了提供标准化的方法之外,还可以定制化的开发java片段.定制化的java片段会在加载时被作为一个独立的类编译,对源数据作处理. morphline关 ...

  7. 前端福利!10个短小却超实用的JavaScript 代码段

    JavaScript正变得越来越流行,它已经成为前端开发的第一选择,并且利用基于JavaScript语言的NodeJS,我们也可以开发出高 性能的后端服务,甚至我还看到在硬件编程领域也出现了JavaS ...

  8. Visual C# 代码段

    代码段是现成的代码段,您可以快速将其插入到您的代码中. 例如,for 代码段创建一个空的 for 循环. 有些代码段为外侧代码段,这些代码段允许您先选择代码行,然后选择要并入选定代码行的代码段. 例如 ...

  9. 十五个常用的jquery代码段【转】

    好的文章顶一个 回到顶部按钮 通过使用 jQuery 中的 animate 和 scrollTop 方法,你无需插件便可创建一个简单地回到顶部动画: 1 // Back to top 2 $('a.t ...

  10. 十五个常用的jquery代码段

    十五个常用的jquery代码段 回到顶部按钮 通过使用 jQuery 中的 animate 和 scrollTop 方法,你无需插件便可创建一个简单地回到顶部动画: 1 // Back to top ...

随机推荐

  1. MariaDB修改配置文件允许远程访问

    MariaDB修改配置文件允许远程访问 最近在使用MariaDB数据库配置用户的远程访问的时候,遇到了一个坑,费了些功夫解决了一下,特此写一下博客,以防下次再遇到的时候忘了解决方案,废话不多说,我们直 ...

  2. Hadoop生态体系组件

    目录: 一.本地数据集上传到数据仓库Hive 二.Hive的基本操作 三.Hive.Mysql.HBase数据互导 正文: 一.本地数据集上传到数据仓库Hive 1.实验数据集的下载 2.数据集的预处 ...

  3. iOS中nil、 Nil、 NULL和NSNull的区别

    参考链接:https://www.jianshu.com/p/c3017ae6684a

  4. Android8.1 MTK平台 SystemUI源码分析之 网络信号栏显示刷新

    SystemUI系列文章 Android8.1 MTK平台 SystemUI源码分析之 Notification流程 Android8.1 MTK平台 SystemUI源码分析之 电池时钟刷新 And ...

  5. Tornado 框架

    Tronado为何物 Tornado全称Tornado Web Server,是一个用Python语言写成的Web服务器兼Web应用框架,由FriendFeed公司在自己的网站FriendFeed中使 ...

  6. 分布式全局唯一ID生成策略​

    一.背景 分布式系统中我们会对一些数据量大的业务进行分拆,如:用户表,订单表.因为数据量巨大一张表无法承接,就会对其进行分库分表. 但一旦涉及到分库分表,就会引申出分布式系统中唯一主键ID的生成问题. ...

  7. css字体效果

    text-shadow还没有出现时,大家在网页设计中阴影一般都是用photoshop做成图片,现在有了css3可以直接使用text-shadow属性来指定阴影.这个属性可以有两个作用,产生阴影和模糊主 ...

  8. canvas应用

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  9. pwn-200

    题目连接 https://adworld.xctf.org.cn/media/task/attachments/49bd95c78386423997fa044a9e750015 借鉴 https:// ...

  10. CCPC 2019 秦皇岛 Angle Beats

    题目 给出P个点,然后给出Q个询问,问从P中选出两个点和给的点能组成直角三角形的方法个数.-O2,时间限制5秒. \[2\leqslant P\leqslant 2000,\qquad 1\leqsl ...