博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OSGI环境中Quartz2.2.0使用数据库连接池
阅读量:6980 次
发布时间:2019-06-27

本文共 10820 字,大约阅读时间需要 36 分钟。

  有任务调度需求的人对Quartz应该不会陌生,目前,Quartz的最新版本是2.2.0,该文章也是基于2.2.0版本。为了保证任务调度系统的HA,对于JobStore我采用了数据库存储的方式。系统出现故障时,系统中正在执行的任务会在数据库中保存,并在系统恢复正常后,Quartz根据misfire的处理策略对任务进行重新调度。

  Quartz2.2.0默认使用的数据库连接池为c3p0。在OSGI环境中,使用该连接池时,会出现连不上数据库的错误。为了解决该问题:主要有两种思路,(1)查看C3P0的源码,修改其中不适合OSGI环境的地方。(2)对Quartz2.2.0提供其它数据库连接池的支持,比如dbcp。对于第一种方法,C3P0的源码繁多,对于工期紧的项目,工作量大,可行度压力大。对于第二种方法,通过了解Quartz2.2.0的源码,发现可行性较高。

  在Quartz中,首先我们看看Quartz是如何使用连接池以及如何设置默认的数据库连接池的。

  在StdSchedulerFactory类的instantiate()方法中,有如下一段:

1 // Set up any DataSources  2         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  3   4         String[] dsNames = cfg.getPropertyGroups(PROP_DATASOURCE_PREFIX);  5         for (int i = 0; i < dsNames.length; i++) {  6             PropertiesParser pp = new PropertiesParser(cfg.getPropertyGroup(  7                     PROP_DATASOURCE_PREFIX + "." + dsNames[i], true));  8   9             String cpClass = pp.getStringProperty(PROP_CONNECTION_PROVIDER_CLASS, null); 10  11             // custom connectionProvider... 12             if(cpClass != null) { 13                 ConnectionProvider cp = null; 14                 try { 15                     cp = (ConnectionProvider) loadHelper.loadClass(cpClass).newInstance(); 16                 } catch (Exception e) { 17                     initException = new SchedulerException("ConnectionProvider class '" + cpClass 18                             + "' could not be instantiated.", e); 19                     throw initException; 20                 } 21  22                 try { 23                     // remove the class name, so it isn't attempted to be set 24                     pp.getUnderlyingProperties().remove( 25                             PROP_CONNECTION_PROVIDER_CLASS); 26  27                     setBeanProps(cp, pp.getUnderlyingProperties()); 28                     cp.initialize(); 29                 } catch (Exception e) { 30                     initException = new SchedulerException("ConnectionProvider class '" + cpClass 31                             + "' props could not be configured.", e); 32                     throw initException; 33                 } 34  35                 dbMgr = DBConnectionManager.getInstance(); 36                 dbMgr.addConnectionProvider(dsNames[i], cp); 37             } else { 38                 String dsJndi = pp.getStringProperty(PROP_DATASOURCE_JNDI_URL, null); 39  40                 if (dsJndi != null) { 41                     boolean dsAlwaysLookup = pp.getBooleanProperty( 42                             PROP_DATASOURCE_JNDI_ALWAYS_LOOKUP); 43                     String dsJndiInitial = pp.getStringProperty( 44                             PROP_DATASOURCE_JNDI_INITIAL); 45                     String dsJndiProvider = pp.getStringProperty( 46                             PROP_DATASOURCE_JNDI_PROVDER); 47                     String dsJndiPrincipal = pp.getStringProperty( 48                             PROP_DATASOURCE_JNDI_PRINCIPAL); 49                     String dsJndiCredentials = pp.getStringProperty( 50                             PROP_DATASOURCE_JNDI_CREDENTIALS); 51                     Properties props = null; 52                     if (null != dsJndiInitial || null != dsJndiProvider 53                             || null != dsJndiPrincipal || null != dsJndiCredentials) { 54                         props = new Properties(); 55                         if (dsJndiInitial != null) { 56                             props.put(PROP_DATASOURCE_JNDI_INITIAL, 57                                     dsJndiInitial); 58                         } 59                         if (dsJndiProvider != null) { 60                             props.put(PROP_DATASOURCE_JNDI_PROVDER, 61                                     dsJndiProvider); 62                         } 63                         if (dsJndiPrincipal != null) { 64                             props.put(PROP_DATASOURCE_JNDI_PRINCIPAL, 65                                     dsJndiPrincipal); 66                         } 67                         if (dsJndiCredentials != null) { 68                             props.put(PROP_DATASOURCE_JNDI_CREDENTIALS, 69                                     dsJndiCredentials); 70                         } 71                     } 72                     JNDIConnectionProvider cp = new JNDIConnectionProvider(dsJndi, 73                             props, dsAlwaysLookup); 74                     dbMgr = DBConnectionManager.getInstance(); 75                     dbMgr.addConnectionProvider(dsNames[i], cp); 76                 } else { 77                     String dsDriver = pp.getStringProperty(PoolingConnectionProvider.DB_DRIVER); 78                     String dsURL = pp.getStringProperty(PoolingConnectionProvider.DB_URL); 79  80                     if (dsDriver == null) { 81                         initException = new SchedulerException( 82                                 "Driver not specified for DataSource: " 83                                         + dsNames[i]); 84                         throw initException; 85                     } 86                     if (dsURL == null) { 87                         initException = new SchedulerException( 88                                 "DB URL not specified for DataSource: " 89                                         + dsNames[i]); 90                         throw initException; 91                     } 92                     try { 93                         PoolingConnectionProvider cp = new PoolingConnectionProvider(pp.getUnderlyingProperties()); 94                         dbMgr = DBConnectionManager.getInstance(); 95                         dbMgr.addConnectionProvider(dsNames[i], cp); 96                     } catch (SQLException sqle) { 97                         initException = new SchedulerException( 98                                 "Could not initialize DataSource: " + dsNames[i], 99                                 sqle);100                         throw initException;101                     }102                 }103 104             }105 106         }

 从上面这段源码可以看出,如果在quartz.properties配置文件中没有设置PROP_CONNECTION_PROVIDER_CLASS或PROP_DATASOURCE_JNDI_URL项的话,则会使用默认的连接池PoolingConnectionProvider。那PoolingConnectionProvider中使用的是什么连接池呢?我们可以看看PoolingConnectionProvider的描述和实现:

1 /** 2  * 

3 * A ConnectionProvider implementation that creates its own 4 * pool of connections. 5 *

6 * 7 *

8 * This class uses C3PO (http://www.mchange.com/projects/c3p0/index.html) as 9 * the underlying pool implementation.

10 * 11 * @see DBConnectionManager12 * @see ConnectionProvider13 * 14 * @author Sharada Jambula15 * @author James House16 * @author Mohammad Rezaei17 */18 public class PoolingConnectionProvider implements ConnectionProvider

 

从类描述中我们就可以看出,该类使用的是C3P0的连接池技术,也就是说Quartz2.2.0默认使用的是C3P0连接池。然后我们看到该类实现了ConnectionProvider接口,首先看看ConnectionProvider的接口定义:

1 /** 2  * Implementations of this interface used by DBConnectionManager 3  * to provide connections from various sources. 4  *  5  * @see DBConnectionManager 6  * @see PoolingConnectionProvider 7  * @see JNDIConnectionProvider 8  * @see org.quartz.utils.weblogic.WeblogicConnectionProvider 9  * 10  * @author Mohammad Rezaei11  */12 public interface ConnectionProvider {13     /*14      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~15      * 16      * Interface.17      * 18      * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~19      */20 21     /**22      * @return connection managed by this provider23      * @throws SQLException24      */25     Connection getConnection() throws SQLException;26     27     28     void shutdown() throws SQLException;29     30     void initialize() throws SQLException;31 }
View Code

 

从接口的描述可以知道,只需要实现该类,然后使用自定义的连接池技术就可以解决文中开头提到的问题了。

思路明确后,我们开始实现,我依照PoolingConnectionProvider的实现写了写了我自己的dbcp连接池的实现类,代码如下:

initialize方法:

1 private void initialize( 2         String dbDriver,  3         String dbURL,  4         String dbUser, 5         String dbPassword,  6         int maxConnections,  7         int maxStatementsPerConnection,  8         String dbValidationQuery, 9         boolean validateOnCheckout,10         int idleValidationSeconds,11         int maxIdleSeconds) throws SQLException, SchedulerException {12         if (dbURL == null) {13             throw new SQLException(14                 "DBPool could not be created: DB URL cannot be null");15         }16         17         if (dbDriver == null) {18             throw new SQLException(19                 "DBPool '" + dbURL + "' could not be created: " +20                 "DB driver class name cannot be null!");21         }22         23         if (maxConnections < 0) {24             throw new SQLException(25                 "DBPool '" + dbURL + "' could not be created: " + 26                 "Max connections must be greater than zero!");27         }28 29         30         datasource = new BasicDataSource(); 31         datasource.setDriverClassName(dbDriver);32             33         datasource.setUrl(dbURL); 34         datasource.setUsername(dbUser); 35         datasource.setPassword(dbPassword);36         datasource.setMaxActive(maxConnections);37         datasource.setMinIdle(1);38         datasource.setMaxWait(maxIdleSeconds);39         datasource.setMaxOpenPreparedStatements(maxStatementsPerConnection);40         41         if (dbValidationQuery != null) {42             datasource.setValidationQuery(dbValidationQuery);43             if(!validateOnCheckout)44                 datasource.setTestOnBorrow(true);45             else46                 datasource.setTestOnReturn(true);47             datasource.setTimeBetweenEvictionRunsMillis(idleValidationSeconds);48         }49     }
View Code

 

1 public Connection getConnection() throws SQLException { 2         return datasource.getConnection(); 3     } 4      5     public void shutdown() throws SQLException { 6         datasource.close(); 7     }     8  9     public void initialize() throws SQLException {10         // do nothing, already initialized during constructor call11         try {12             this.initialize(this.driver, this.URL, this.user, this.password, 13                     maxConnections, maxStatementsPerConnection, dbValidationQuery, 14                     validateOnCheckout, idleValidationSeconds, maxIdleSeconds);15         } catch (SchedulerException e) {16             // TODO Auto-generated catch block17             throw new SQLException(e);18         }19     }
View Code

 

然后在quartz.properties配置文件中配置org.quartz.dataSource.dbcpDS.connectionProvider.class属性,如下:

org.quartz.dataSource.dbcpDS.connectionProvider.class: com.dawning.cloudview.app.scheduleframe.service.scheduleframe.pool.DbcpConnectionProvider

启动OSGI环境,加载DBCP所需的bundle,然后测试。通过测试,发现能正常连上数据库。该方法可行。

转载于:https://www.cnblogs.com/softwindzy/p/3291187.html

你可能感兴趣的文章
ondblog 修改informix日志模式
查看>>
后海日记(8)
查看>>
遮罩效果的实现
查看>>
SQLSERVER存储过程基本语法使用
查看>>
sql server时间转换
查看>>
insert into与insert ignore以及replace into的区别
查看>>
JS+CSS控制左右切换鼠标可控的无缝图片滚动代码
查看>>
C# 实现HTML转换成图片的方法
查看>>
Exceptions Interview Questions
查看>>
JAVA-基础(Class对象及反射)
查看>>
一个疯狂想法
查看>>
c# 关闭软件 进程 杀死进程
查看>>
swift集成alamofire的简单封装
查看>>
javascript模块化、模块加载器初探
查看>>
PL/SQL Developer远程访问Oracle数据库
查看>>
我的友情链接
查看>>
eclipse插件安装方法
查看>>
Javascript中的字符串链接和Array.join()方法时间效率对比
查看>>
为什么用Immutable.js代替普通js对象?
查看>>
Ossim系统常见测试方法
查看>>