activiti 資料庫連線配置
1.1.1. 前言
當我們程式配置了DataSource,activiti 工作流引擎是如何開啟資料庫連線呢?有沒有其他的方式配置資料庫連線呢?
這一個章節主要講解activiti 工作流引擎資料庫連線的其他配置方式,以及底層如何封裝連線,開啟連線操作資料庫。本章先從配置入手,瞭解常用的配置方法,以及引領大家閱讀程式碼,使大家的印象更深刻,而不是隻會配置,瞭解原理才是最重要的。
1.1.2. Datadource方式配置
Datasource的配置如下所示:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/activiti" />
<property name="username" value="root" />
<property name="password" value="********" />
</bean>
工作流引擎的配置如下所示:
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="dataSource" ref=”dataSource” />
</bean>
1.1.3. 普通方式配置
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://
<property name="username" value="root" />
<property name="password" value="********" />
</bean>
1.1.4. jndi方式配置
此種配置需要在server.xml中配置具體的資料來源資訊,具體的配置步驟如下:
1、在tomcat伺服器的lib目錄下加入資料庫連線的驅動jar包
2、修改tomcat伺服器的conf目錄下server.xml配置檔案
3、修改tomcat伺服器的conf目錄下server.xml配置檔案
開啟server.xml配置檔案,可以看到裡面自帶的一個全域性JNDI配置,如下圖所示:
編輯server.xml檔案,新增全域性JNDI資料來源配置,配置如下:
<Resource
name="jdbc/mysql"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"47
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"50 url="jdbc:mysql://192.168.1.144:3306/leadtest?useUnicode=true&characterEncoding=utf-8"/>
經過以上的兩個步驟,全域性JNDI資料來源就配置好了,在上述的server.xml檔案中,配置了MySQL資料庫的全域性JNDI資料來源。
上面的配置完成了程式中怎麼使用呢?
dataSourceJndiName
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
<property name="dataSourceJndiName" ref=”dataSourceJndiName” />
</bean>
1.1.5. initDataSource原始碼
上面的三種配置足夠我們用了,那麼這三種方式那種優先順序比較高,換言之,那種方式的優先順序比較高呢。下面我們就開始跟進原始碼看看activiti核心 是如何解析執行的吧。
首先進入org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl查詢initDataSource()方法詳細解析如下:
protected void initDataSource() {
//首先判斷dataSource是否存在看來這個優先順序是最高的了。
if (dataSource==null) {
//如果dataSource不存在則查詢dataSourceJndiName是否配置了,如果jndi配置了使用。
if (dataSourceJndiName!=null) {
try {
//查詢jndi配置資訊。
dataSource = (DataSource) new InitialContext().lookup(dataSourceJndiName);
} catch (Exception e) {
throw new ActivitiException("couldn't lookup datasource from "+dataSourceJndiName+": "+e.getMessage(), e);
}
//如果上面的datasource和jndi都不存在就直接使用普通的方式 進行配置獲取初始化PooledDataSource
} else if (jdbcUrl!=null) {
//任何一個為報錯
if ( (jdbcDriver==null) || (jdbcUrl==null) || (jdbcUsername==null) ) {
throw new ActivitiException("DataSource or JDBC properties have to be specified in a process engine configuration");
}
//根據配置建立PooledDataSource 物件
PooledDataSource pooledDataSource =
new PooledDataSource(ReflectUtil.getClassLoader(), jdbcDriver, jdbcUrl, jdbcUsername, jdbcPassword );
//下面是配置其他的資料庫連線池資訊
if (jdbcMaxActiveConnections > 0) {
pooledDataSource.setPoolMaximumActiveConnections(jdbcMaxActiveConnections);
}
if (jdbcMaxIdleConnections > 0) {
pooledDataSource.setPoolMaximumIdleConnections(jdbcMaxIdleConnections);
}
if (jdbcMaxCheckoutTime > 0) {
pooledDataSource.setPoolMaximumCheckoutTime(jdbcMaxCheckoutTime);
}
if (jdbcMaxWaitTime > 0) {
pooledDataSource.setPoolTimeToWait(jdbcMaxWaitTime);
}
if (jdbcPingEnabled == true) {
pooledDataSource.setPoolPingEnabled(true);
if (jdbcPingQuery != null) {
pooledDataSource.setPoolPingQuery(jdbcPingQuery);
}
pooledDataSource.setPoolPingConnectionsNotUsedFor(jdbcPingConnectionNotUsedFor);
}
if (jdbcDefaultTransactionIsolationLevel > 0) {
pooledDataSource.setDefaultTransactionIsolationLevel(jdbcDefaultTransactionIsolationLevel);
}
dataSource = pooledDataSource;
}
if (dataSource instanceof PooledDataSource) {
//呼叫forceCloseAll方法,如果不呼叫Ibatis 資料庫池子拿不到上面的資料庫配置連線資訊
((PooledDataSource)dataSource).forceCloseAll();
}
}
//如果程式沒有配置databaseType 資料庫型別則activiti自己根據連線字串開啟一次請求獲取型別
if (databaseType == null) {
initDatabaseType();
}
}
1.1.6. databaseType 優化
initDatabaseType()詳細的方法如下:
//說白了就是反射資料庫拿到元資料資訊進行判斷 這裡最好配置一次可以優化的地方,沒有配置的話要開啟一次資料庫連線
public void initDatabaseType() {
Connection connection = null;
try {
connection = dataSource.getConnection();
//根據連接獲取到元資料資訊
DatabaseMetaData databaseMetaData = connection.getMetaData();
//獲取到資料庫生產廠商資訊
String databaseProductName = databaseMetaData.getDatabaseProductName();
log.debug("database product name: '{}'", databaseProductName);
//因為市面上的資料庫庫廠商是固定的所以這裡一次性載入到記憶體然後根據查詢的資料庫廠商匹配
databaseType = databaseTypeMappings.getProperty(databaseProductName);
if (databaseType==null) {
throw new ActivitiException("couldn't deduct database type from database product name '"+databaseProductName+"'");
}
} catch (SQLException e) {
} finally {
try {
//上面打開了連線所以這裡釋放了連線
if (connection!=null) {
connection.close();
}
} catch (SQLException e) {
log.error("Exception while closing the Database connection", e);
}
}
}
資料庫datatype與資料庫廠商的對映如下:
public static final String DATABASE_TYPE_H2 = "h2";
public static final String DATABASE_TYPE_HSQL = "hsql";
public static final String DATABASE_TYPE_MYSQL = "mysql";
public static final String DATABASE_TYPE_ORACLE = "oracle";
public static final String DATABASE_TYPE_POSTGRES = "postgres";
public static final String DATABASE_TYPE_MSSQL = "mssql";
public static final String DATABASE_TYPE_DB2 = "db2";
protected static Properties getDefaultDatabaseTypeMappings() {
Properties databaseTypeMappings = new Properties();
databaseTypeMappings.setProperty("H2", DATABASE_TYPE_H2);
databaseTypeMappings.setProperty("HSQL Database Engine", DATABASE_TYPE_HSQL);
databaseTypeMappings.setProperty("MySQL", DATABASE_TYPE_MYSQL);
databaseTypeMappings.setProperty("Oracle", DATABASE_TYPE_ORACLE);
databaseTypeMappings.setProperty("PostgreSQL", DATABASE_TYPE_POSTGRES);
databaseTypeMappings.setProperty("Microsoft SQL Server", DATABASE_TYPE_MSSQL);
databaseTypeMappings.setProperty(DATABASE_TYPE_DB2,DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/NT",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/NT64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDP",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUX",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUX390",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXX8664",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXZ64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/LINUXPPC64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/400 SQL",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/6000",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDB iSeries",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/AIX64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/HPUX",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/HP64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/SUN",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/SUN64",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/PTX",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2/2",DATABASE_TYPE_DB2);
databaseTypeMappings.setProperty("DB2 UDB AS400", DATABASE_TYPE_DB2);
return databaseTypeMappings;
}
上面詳細的總結了activiti 工作流引擎常用的資料庫連線配置,以及優先順序的問題,資料庫databaseType可以優化效能。