标签:saas 数据源 spring spring多数据源管理
开发saas程序时,要求每个公司使用一个数据库,当使用spring时如何配置数据源使得每个公司使用不同的数据库连接?1、将公司id存放到一个ThreadLocal变量中,每次请求时设置,使得每次访问数据源可以从ThreadLocal获取当前请求所属的公司id。
/** * 用来存放当前线程的数据 */ public class ThreadHolder { //公司id private static ThreadLocal<String> localDid = new ThreadLocal<String>(); public static void putSp(String sp) { localDid.set(sp); } public static String getSp() { if (localDid.get() == null) return ""; else return (String)localDid.get(); } }2、在每次请求时调用ThreadHolder.putSp方法设置公司id。
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="xxxx" /> <property name="jdbcUrl" value="xxx" /> <property name="user" value="user" /> <property name="password" value="password" /> <property name="minPoolSize" value="1" /> <property name="maxPoolSize" value="800" /> <property name="maxIdleTime" value="25000" /> <property name="acquireIncrement" value="1" /> <property name="maxStatements" value="0" /> <property name="initialPoolSize" value="100" /> <property name="idleConnectionTestPeriod" value="18000" /> <property name="acquireRetryAttempts" value="10" /> <property name="acquireRetryDelay" value="1000" /> <property name="breakAfterAcquireFailure" value="false" /> <property name="checkoutTimeout" value="10000" /> <property name="testConnectionOnCheckout" value="false" /> </bean>修改成:
<bean id="dataSource" class="com.sangfor.frame.multiclient.MultiClientDataSource"> <property name="dataSource"> <ref bean="dataSourceDefault" /> </property> </bean> <bean id="dataSourceDefault" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="xxxx" /> <property name="jdbcUrl" value="xxx" /> <property name="user" value="user" /> <property name="password" value="password" /> <property name="minPoolSize" value="1" /> <property name="maxPoolSize" value="800" /> <property name="maxIdleTime" value="120" /> <property name="acquireIncrement" value="1" /> <property name="maxStatements" value="0" /> <property name="initialPoolSize" value="100" /> <property name="idleConnectionTestPeriod" value="65" /> <property name="acquireRetryAttempts" value="10" /> <property name="acquireRetryDelay" value="1000" /> <property name="breakAfterAcquireFailure" value="false" /> <property name="checkoutTimeout" value="10000" /> </bean>MultiClientDataSource:
public class MultiClientDataSource implements DataSource { public static final String DBNAME_PREFIX = "CLIENT_"; private ComboPooledDataSource dataSource = null; private Map<String,DataSource> dsMap = new HashMap<String,DataSource>(); private static Object lock=new Object(); public DataSource addDataSource(String did){ try{ synchronized (lock) { if (dsMap==null) dsMap = new HashMap<String,DataSource>(); DataSource ds = dsMap.get(did); if (ds != null) return ds; ComboPooledDataSource newDs = getNewDataSource(did); dsMap.put(did, newDs); } }catch(Exception e){ e.printStackTrace(); } return dsMap.get(did); } public void removeDataSource(String did){ if (dsMap==null) return; dsMap.remove(did); } private ComboPooledDataSource getNewDataSource(String did) throws Exception{ ComboPooledDataSource ds = new ComboPooledDataSource(); ds.setDriverClass("xxx");//driver class String jdbcUrl = "jdbc:mysql://127.0.0.1" //一般将ip配置在配置文件 +":3306"+"/"+ DBNAME_PREFIX + did + "?useUnicode=true&characterEncoding=utf-8"; ds.setJdbcUrl(jdbcUrl); ds.setUser("user"); ds.setPassword("password"); ds.setMinPoolSize(1); ds.setMaxPoolSize(800); ds.setMaxIdleTime(2000); ds.setAcquireIncrement(1); ds.setMaxStatements(0); ds.setInitialPoolSize(100); ds.setIdleConnectionTestPeriod(1800); ds.setAcquireRetryAttempts(10); ds.setAcquireRetryDelay(1000); ds.setBreakAfterAcquireFailure(false); ds.setCheckoutTimeout(10000); ds.setPreferredTestQuery(" select FORMID from FLOW_FORM where 1 = 2"); ds.setTestConnectionOnCheckout(false); return ds; } private void initDsMap()throws Exception{ try{ if (dsMap==null){ dsMap = new HashMap<String,DataSource>(); } }catch(Exception e){ throw new Exception(e); } } public Connection getConnection() throws SQLException { return getDataSource().getConnection(); } public Connection getConnection(String arg0, String arg1) throws SQLException { return getDataSource().getConnection(arg0, arg1); } public PrintWriter getLogWriter() throws SQLException { return getDataSource().getLogWriter(); } public int getLoginTimeout() throws SQLException { return getDataSource().getLoginTimeout(); } public void setLogWriter(PrintWriter arg0) throws SQLException { getDataSource().setLogWriter(arg0); } public void setLoginTimeout(int arg0) throws SQLException { getDataSource().setLoginTimeout(arg0); } public DataSource getDataSource(String dataSourceName)throws SQLException { try{ if(dataSourceName==null||dataSourceName.equals("")){ return this.dataSource; }else{ DataSource ds = dsMap.get(dataSourceName); if (ds!=null) return ds; else return null; } }catch(NoSuchBeanDefinitionException ex){ throw new SQLException("There is not the dataSource <name:"+dataSourceName+"> in the applicationContext!"); } } public void setDataSource(ComboPooledDataSource dataSource) { this.dataSource = dataSource; } public ComboPooledDataSource getDataSource()throws SQLException{ String did = ThreadHolder.getSp(); DataSource ds = getDataSource(did); if (ds == null) return null; else return (ComboPooledDataSource)ds; } public DataSource getDefaultDataSource()throws SQLException{ return dataSource; } @Override public boolean isWrapperFor(Class<?> arg0) throws SQLException { // TODO Auto-generated method stub return false; } @Override public <T> T unwrap(Class<T> arg0) throws SQLException { // TODO Auto-generated method stub return null; } }实现原理:
标签:saas 数据源 spring spring多数据源管理
原文地址:http://blog.csdn.net/kingofworld/article/details/44757079