67,549
社区成员




/**对接开发应用表*/
CREATE TABLE `cmm_dev` (
`DevID` varchar(16) NOT NULL,
`Name` varchar(128) DEFAULT NULL,
`ServerID` int(11) DEFAULT NULL, -----与DbInfo的Id对应,但未设置外键关系
PRIMARY KEY (`DevID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/**数据源表*/
CREATE TABLE `cmm_db_info` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`IP` varchar(50) DEFAULT NULL,
`Port` int(11) DEFAULT NULL,
`DbName` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
动态数据源类:
package cn.util.dao.Helper;
import java.util.Map;
import org.apache.commons.dbcp.BasicDataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import cn.util.comment.domain.DbInfo;
public class DynamicDataSource extends AbstractRoutingDataSource {
private Map<Object, Object> _targetDataSources;
@Override
protected Object determineCurrentLookupKey() {
Object obj = DbContextHolder.getDbType();
if(obj == null){
obj = "default";
}
System.out.println("OBJ-->"+obj);
return obj;
}
public void setTargetDataSources(Map<Object, Object> targetDataSources) {
this._targetDataSources = targetDataSources;
super.setTargetDataSources(this._targetDataSources);
afterPropertiesSet();
}
public void addTargetDataSource(String key, BasicDataSource dataSource) {
this._targetDataSources.put(key, dataSource);
this.setTargetDataSources(this._targetDataSources);
}
public BasicDataSource createDataSource(String driverClassName,String url,
String username, String password,int maxIdle,int maxActive) {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setMaxActive(maxActive);
dataSource.setMaxIdle(maxIdle);
dataSource.setInitialSize(1);
dataSource.setDefaultAutoCommit(true);
return dataSource;
}
public void selectDataSource(Integer serverId){
Object obj = DbContextHolder.getDbType();
if("0".equals(serverId+"")){
DbContextHolder.setDbType("default");
return;
}
if(obj != null && obj.equals(serverId+"")){
return;
}else{
BasicDataSource dataSource = this.getDataSource(serverId);
this.setDataSource(serverId, dataSource);
}
}
public BasicDataSource getDataSource(Integer serverId){
String driver = DBConfig.getDriver();
String username = DBConfig.getUsername();
String password = DBConfig.getPass();
int maxActive = DBConfig.getMaxActive();
int maxIdle = DBConfig.getMaxIdle();
DbInfo dbInfo = DataSourceHelper.getDbInfo(serverId);
String url = "jdbc:mysql://"+dbInfo.getIp()+":"+dbInfo.getPort()+"/"+dbInfo.getDbName()
+"?characterEncoding=utf-8&allowMultiQueries=true&autoReconnect=true";
BasicDataSource dataSource = this.createDataSource(driver, url, username, password, maxIdle, maxActive);
return dataSource;
}
public void setDataSource(Integer serverId,BasicDataSource dataSource){
this.addTargetDataSource(serverId+"", dataSource );
DbContextHolder.setDbType(serverId+"");
}
}
============================================================================
帮助类,主要是加载DbInfo用.
package cn.util.dao.Helper;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import cn.util.comment.dao.DbInfoDao;
import cn.util.comment.domain.CommentInfo;
import cn.util.comment.domain.DbInfo;
import cn.util.comment.helper.ApplicationContextHelper;
import cn.util.comment.helper.DateHelper;
import cn.util.comment.service.logic.CommentInfoLogic;
/**
* @createTime 2013-1-29上午10:23:52
* @author KING
* @version 1.0.0.0
*/
public class DataSourceHelper {
private DbInfoDao dbInfoDao;
private static Map<Integer,DbInfo> dataSourceMap = new ConcurrentHashMap<Integer,DbInfo>();
public void loadAllDbInfo(){
List<DbInfo> dbinfoList = dbInfoDao.findListByParams(null);
if(dbinfoList != null && dbinfoList.size() >0){
for (DbInfo dbInfo : dbinfoList) {
if(dbInfo != null ){
dataSourceMap.put(dbInfo.getId(), dbInfo);
}
}
}
}
public static DbInfo getDbInfo(Integer id){
if(!dataSourceMap.containsKey(id)){
DataSourceHelper.reLoadDbInfo();
}
return dataSourceMap.get(id);
}
public static void reLoadDbInfo(){
Map<Integer,DbInfo> tempMap = new ConcurrentHashMap<Integer,DbInfo>();
DbInfoDao dbInfoDao = (DbInfoDao) ApplicationContextHelper.getBean("dbInfoDao");
List<DbInfo> dbinfoList = dbInfoDao.findListByParams(null);
if(dbinfoList != null && dbinfoList.size() >0){
for (DbInfo dbInfo : dbinfoList) {
if(dbInfo != null ){
tempMap.put(dbInfo.getId(), dbInfo);
}
}
}
dataSourceMap = tempMap;
}
public static void main(String... args){
CommentInfoLogic logic = (CommentInfoLogic) ApplicationContextHelper.getBean("commentInfoLogic");
CommentInfo info = new CommentInfo();
info.setId(DateHelper.getUUID());
info.setCreateTime(new Date());
logic.addCommentInfo(1+"", info);
logic.addCommentInfo("test", info);
}
}
============================================================================
Context用于存放当环境的上下文标识类
package cn.util.dao.Helper;
public class DbContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
public static void setDbType(String dbType) {
contextHolder.set(dbType);
}
public static String getDbType() {
return ((String)contextHolder.get());
}
public static void clearDbType() {
contextHolder.remove();
}
}
============================SPRING DataSource配置============================
<!-- 加载Properties资源文件配置 -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/jdbc.properties</value>
</list>
</property>
</bean>
<!-- 数据库连接池 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driver}" />
<property name="url" value="${dbmaster.url}" />
<property name="username" value="${dbmaster.username}" />
<property name="password" value="${dbmaster.password}" />
<property name="maxActive" value="${db.maxActive}"/>
<property name="maxIdle" value="${db.maxIdle}"/>
<property name="initialSize" value="1"/>
<property name="defaultAutoCommit" value="true" />
</bean>
<bean id="dynDataSource" class="cn.util.dao.Helper.DynamicDataSource">
<property name="targetDataSources">
<map>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSource" />
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:config/mybatis/mybatis-config.xml"/>
<property name="dataSource" ref="dynDataSource" />
</bean>
<!-- 数据库的事务管理器配置 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dynDataSource" />
</bean>
<!-- 使用annotation定义数据库事务,这样可以在类或方法中直接使用@Transactional注解来声明事务 -->
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
<!--sqlSession模板定义-->
<bean id="sqlReadSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
<bean id="commentInfoDao" class="cn.util.comment.dao.CommentInfoDao">
<property name="sqlReadSession">
<ref bean="sqlReadSession"/>
</property>
</bean>
<bean id="devDao" class="cn.util.comment.dao.DevDao">
<property name="sqlReadSession">
<ref bean="sqlReadSession"/>
</property>
</bean>
<!-- logic层注入 -->
<bean id="commentInfoLogic" class="cn.util.comment.service.logic.CommentInfoLogic">
<property name="commentInfoDao">
<ref bean="commentInfoDao"/>
</property>
<property name="devDao">
<ref bean="devDao"/>
</property>
</bean>
<bean id="commentInfoService" class="cn.util.comment.service.CommentInfoService">
<property name="commentInfoLogic">
<ref bean="commentInfoLogic"/>
</property>
</bean>
====================================STRUTS 配置==================================
<struts>
<package name="cmmService" extends="struts-default" namespace="/service/CmmService">
<action name="Add" class="commentInfoService" method="addCommentInfo">
<result>/index.jsp</result>
</action>
</package>
</struts>
public static void main(String... args){
CommentInfoLogic logic = (CommentInfoLogic) ApplicationContextHelper.getBean("commentInfoLogic");
CommentInfo info = new CommentInfo();
info.setId(DateHelper.getUUID());
info.setCreateTime(new Date());
logic.addCommentInfo("1", info);
logic.addCommentInfo("2", info);
}
结果两条数据都是插入到了默认数据库了.这样就和web请求是一样的结果.
就是获得的session里面没有动态添加进去的datasource了.
这是那里的原因呢.
好像差一点点,就能解决了,就是不能捅破这最后一层纸呀.郁闷哟.
public static void main(String... args){
CommentInfoLogic logic = (CommentInfoLogic) ApplicationContextHelper.getBean("commentInfoLogic");
CommentInfo info = new CommentInfo();
info.setId(DateHelper.getUUID());
info.setCreateTime(new Date());
logic.addCommentInfo("1", info);
logic.addCommentInfo("2", info);
}
但是,现在通过web请求,做如下测试.
请求URL:
http://localhost:8081/comment_service_webv3/service/CmmService/Add?参数串
将logic代码稍做调整.
public String addCommentInfo(String devID, CommentInfo commentInfo) {
Map<String, Object> params = new HashMap<String, Object>();
Dev dev = devDao.findByParams(params);
if(dev != null && !StringHelper.Empty.equals(dev.getServerID())){
//变库
DynamicDataSource dynamicDataSource = (DynamicDataSource) ApplicationContextHelper.getBean("dynDataSource");
//将数据库强制变为2库.
dynamicDataSource.selectDataSource(2);
}
commentInfo = commentInfoDao.insert(commentInfo);
return "";
}
结果:
预期该条数据应该查入2库,但实际却仍然插入spring配置的默认datasource库(<property name="defaultTargetDataSource" ref="dataSource" />)里面.
思考:这不科学呀,我两种方法基本没有区别呀.最后经过比对,找了大概出错的地方,是数据库层getSession出的不一样,但是不知道是为什么.
第一种通过代码测试,debug截图如下图,发现其获得session中有动态添加进去的datasource.