最近在试用wabacus,遇到一个问题:一个应用需要连接多个数据,除了一个主数据库以外,其他数据库连接参数只能在运行时才能从主数据库取得并进行动态创建数据。 wabacus本身是支持多数据库的,但不支持在运行期动态创建数据源。通过咨询wabacus作者以及研究wabacus的源码,想出了一种实现办法。在这里把实现方法记录一下,方便自己也方便别人。
=========================================================
思路:
1、搞清框架中创建数据源的思路;
2、想办法模仿并创建数据源,并把创建好的数据源放入框架数据源集合;
实现:
在作者老大指点下,了解了框架中创建数据源并入数据源集合的入口:
com.wabacus.config.ConfigLoadManager 中 loadDataSources 方法的下面几句:
((AbsDataSource)providerObj).setName(name); //
((AbsDataSource)providerObj).loadConfig(eleDataSource); //根据配置信息创建数据源
mDataSources.put(name,((AbsDataSource)providerObj)); //把数据源放入框架数据源集合
……
Config.getInstance().setMDataSources(mDataSources);
搞明白这个,剩下的事情就不难了,整个实现比预期的要简单很多。作一个工具类来实现新增自定义数据源:
//CustomConfigUtil.java
/**
* @CopyRright (c)2011: BrokenStone
* @Project: csbhxt
* @File: CustomeConfigUtil.java
* @JDK version used: JDK1.6 @
* @Author: BrokenStone
* @Blog: http://sheng.javaeye.com)
* @Email: wdmsyf@yahoo.com
* @since: 2012-5-13
* @Ver: 1.0
*/
package com.iteye.sheng.wabacus.extend.config;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import com.wabacus.config.Config;
import com.wabacus.config.database.datasource.AbsDataSource;
import com.wabacus.config.database.datasource.DriverManagerDataSource;
import com.wabacus.exception.WabacusConfigLoadingException;
/**
* wabacus框架配置参数增强工具类
*/
public class CustomConfigUtil {
private static final Log log = LogFactory.getLog(CustomConfigUtil.class);
/**
* 增加自定义数据源
* @param eleDataSource 数据源配置参数的Element
*/
public static void addCustomeDataSource(Element eleDataSource) {
Map<String, AbsDataSource> mDataSources = Config.getInstance().getMDataSources();
String name = eleDataSource.attributeValue("name");
if (StringUtils.isEmpty(name)) {
throw new WabacusConfigLoadingException("必须配置数据源的name属性");
}
name = name.trim();
if (mDataSources.containsKey(name)) {
throw new WabacusConfigLoadingException("配置的数据源:" + name + "存在重复");
}
String provider = eleDataSource.attributeValue("type");
if (provider == null || provider.trim().equals("")) {
provider = DriverManagerDataSource.class.getName();
}
Object providerObj = null;
try {
Class c_provider = Class.forName(provider);
providerObj = c_provider.newInstance();
} catch (ClassNotFoundException e1) {
throw new WabacusConfigLoadingException("无法加载数据源类:" + provider, e1);
} catch (Exception e) {
throw new WabacusConfigLoadingException("数据源类:" + provider + "无法实例化", e);
}
if (!(providerObj instanceof AbsDataSource)) {
throw new WabacusConfigLoadingException("配置的数据源类:" + provider + "没有继承超类" + AbsDataSource.class.getName());
}
((AbsDataSource) providerObj).setName(name);
((AbsDataSource) providerObj).loadConfig(eleDataSource);
mDataSources.put(name, ((AbsDataSource) providerObj));
}
/**
* 增加自定义数据源
* @param params
*/
public static void addCustomeDataSource(Map<String, String> params){
DocumentFactory df = new DocumentFactory();
Element newDSElement = df.createElement("datasource");
newDSElement.addAttribute("name", params.get("name"));
newDSElement.addAttribute("type", params.get("type"));
newDSElement.addAttribute("dbtype", params.get("dbtype"));
((newDSElement.addElement("property")).addAttribute("name", "driver")).setText( getParam(params, "driver") );
((newDSElement.addElement("property")).addAttribute("name", "url")).setText( getParam(params, "url") );
((newDSElement.addElement("property")).addAttribute("name", "user")).setText( getParam(params, "user") );
((newDSElement.addElement("property")).addAttribute("name", "password")).setText( getParam(params, "password", "") );
((newDSElement.addElement("property")).addAttribute("name", "max_size")).setText( getParam(params, "max_size", "20") );
((newDSElement.addElement("property")).addAttribute("name", "min_size")).setText( getParam(params, "min_size", "5") );
((newDSElement.addElement("property")).addAttribute("name", "timeout")).setText( getParam(params, "timeout", "100"));
((newDSElement.addElement("property")).addAttribute("name", "max_statements")).setText( getParam(params, "max_statements", "100"));
((newDSElement.addElement("property")).addAttribute("name", "idle_test_period")).setText( getParam(params, "idle_test_period", "50"));
((newDSElement.addElement("property")).addAttribute("name", "acquire_increment")).setText( getParam(params, "acquire_increment", "2"));
addCustomeDataSource(newDSElement);
}
private static String getParam(Map<String, String> params, String name){
return params.get(name);
}
private static String getParam(Map<String, String> params, String name, String defaultValue){
return StringUtils.isEmpty(params.get(name))? defaultValue : params.get(name);
}
}
使用例子如下:
private void addCustomeDataSourceTest(){
Map<String, String> dsParamMap = new HashMap<String, String>();
dsParamMap.put("name", "MyCustomDS1");
dsParamMap.put("type", "com.wabacus.config.database.datasource.C3P0DataSource");
dsParamMap.put("dbtype", "com.wabacus.config.database.type.MySql");
dsParamMap.put("driver", "com.mysql.jdbc.Driver");
dsParamMap.put("url", "jdbc:mysql://localhost:3306/phonegap?useUnicode=true&characterEncoding=UTF-8");
dsParamMap.put("user", "root");
dsParamMap.put("password", "");
dsParamMap.put("max_size", "20");
dsParamMap.put("min_size", "5");
dsParamMap.put("timeout", "100");
dsParamMap.put("max_statements", "100");
dsParamMap.put("idle_test_period", "50");
dsParamMap.put("acquire_increment", "2");
CustomConfigUtil.addCustomeDataSource( dsParamMap );
AbsDataSource ds = Config.getInstance().getDataSource("MyCustomDS1");
Connection conn = ds.getConnection();
Statement stmt = null;
ResultSet rs = null;
try{
stmt = conn.createStatement();
boolean isSucc = stmt.execute("SELECT * FROM employee");
if(isSucc){
rs = stmt.getResultSet();
StringBuffer sb = new StringBuffer("");
while(rs.next()){
sb.append("id = ").append(rs.getInt("id")).append(", ")
.append("firstName = ").append(rs.getString("firstName")).append(", ")
.append("lastName = ").append(rs.getString("lastName")).append(", ")
.append("managerId = ").append(rs.getString("managerId")).append(", ")
.append("title = ").append(rs.getString("title")).append(", ")
.append("department = ").append(rs.getString("department")).append(", ")
.append("officePhone = ").append(rs.getString("officePhone")).append(", ")
.append("cellPhone = ").append(rs.getString("cellPhone")).append(", ")
.append("email = ").append(rs.getString("email")).append(", ")
.append("city = ").append(rs.getString("city")).append(", ")
.append("picture = ").append(rs.getString("picture")).append("\r\n ");
}
log.debug(sb.toString());
System.out.println(sb.toString());
}else{
log.error("执行SQL语句失败。");
}
}catch(SQLException ex){
log.error(ex);
}finally{
try{
if(rs!=null) rs.close();
rs = null;
}catch(SQLException ex){
log.warn(ex);
}
try{
if(stmt!=null) stmt.close();
stmt = null;
}catch(SQLException ex){
log.warn(ex);
}
try{
if(conn!=null) conn.close();
conn = null;
}catch(SQLException ex){
log.warn(ex);
}
}
}
再次感谢作者提供如此优秀的开发框架并给予无私指导。