`

实现在运行期动态创建数据源(连接池)

 
阅读更多

      最近在试用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); 
		}       
	} 
}
 

再次感谢作者提供如此优秀的开发框架并给予无私指导。
分享到:
评论

相关推荐

    spring+hibernate整合需要的一些包

    1. **CGLIB**:全称为Code Generation Library,是一个Java字节码处理库,用于在运行期动态创建类或增强已有类的功能。在Spring AOP(面向切面编程)中,当目标对象没有实现接口时,Spring会使用CGLIB来创建代理对象...

    Spring框架,AOP,Spring整合Mybatis

    而CGLIB(Code Generation Library)是在运行期通过字节码技术动态生成子类来实现代理,即使目标对象没有实现接口也能进行代理。CGLIB在Spring框架中被广泛用于那些没有实现接口的类的代理。 Spring整合Mybatis是另...

    jsp复习资料

    1. **动态网页概念**:动态网页指的是在服务器端运行的程序或网页,它们能够根据不同的客户端请求、不同的时间点返回不同的内容,从而实现更为丰富的交互效果。 2. **URL组成部分**: - **协议**:如HTTP(超文本...

    java部分面试题.pdf

    - AOP:在不修改源代码的情况下,通过预编译方式或运行期动态代理实现程序功能的统一维护的一种技术,常用于日志、事务等。 - SOC:一个类应该只有一个引起变化的原因,每个类应有一个单一的职责,提高可维护性。 ...

    分布式架构说明

    - **连接管理**:在微服务架构下,由于服务数量较多,每个服务都需要与多个数据库建立连接,因此必须有效管理数据库连接池,以避免资源浪费和性能瓶颈。 **2.4 最终一致性组件** - **组件功能**:为了处理分布式...

    Websphere portal tuning调优

    动态装配是指在运行时动态加载和配置门户组件的能力,而过程集成则是指与其他企业应用程序和服务之间的集成。 1. **动态组件加载**:支持按需加载门户组件,减少启动时间和内存占用。 2. **工作流集成**:实现与...

    常用的jAVA包的作用

    DBCP 是基于Jakarta commons-pool的数据库连接池实现,它可以高效地复用数据库连接,避免频繁创建和销毁连接所带来的开销。在实际应用中,特别是在高并发环境下,使用DBCP可以显著提升系统的性能和稳定性。 #### 10...

    Visual C++实践与提高-COM和COM+篇『PDF』

    7.4.4 创建数据源 7.4.5 编写客户程序 7.4.6 三层软件应用模型 小结 第8章 OLE文档与ActiveX文档 8.1 OLE文档基础知识 8.1.1 OLE文档服务器与包容器 8.1.2 OLE服务体系结构 8.1.3 链接与嵌入技术 8.1.4 现场激活...

    hibernate使用的jar包

    3. ** cglib-nodep-2.1_3.jar**:CGLIB是一个高性能的代码生成库,用于在运行期扩展Java类与实现Java接口。Hibernate在没有JDK代理支持的情况下使用CGLIB来创建实体类的代理对象,以便于实现懒加载和其他高级特性。 ...

    Android设计思想解读开源框架.pdf

    - **Subject**:作为Observable和Observer的桥梁,允许多个观察者订阅同一个数据源。 - **Schedulers**:RxJava中的调度器,用于控制操作符的执行顺序和执行位置。 **6.3 事件变换设计** - **操作符**:RxJava提供...

    ssh jar包介绍

    1. **freemarker-2.3.15.jar**:FreeMarker是一个用于生成输出文本的模板引擎,它可以与任何能够输出纯文本的数据源一起工作。在Struts2框架中,主要用于处理页面模板(例如JSP页面模板),使得开发者能够更方便地...

    ASP3《高级编程》(第一部分)

    10.2.4 数据源对象 301 10.2.5 数据绑定 308 10.2.6 更新数据 316 10.3 在服务器和客户之间传输数据 319 10.3.1 基于服务器的组件 319 10.3.2 DataSpace对象 320 10.3.3 使用服务器端组件的优点 322 10.3.4 ...

    ASP3《高级编程》(第二部分)

    10.2.4 数据源对象 301 10.2.5 数据绑定 308 10.2.6 更新数据 316 10.3 在服务器和客户之间传输数据 319 10.3.1 基于服务器的组件 319 10.3.2 DataSpace对象 320 10.3.3 使用服务器端组件的优点 322 10.3.4 ...

Global site tag (gtag.js) - Google Analytics