- 浏览: 312145 次
- 性别:
- 来自: 青岛
文章分类
- 全部博客 (140)
- 技术笔记 (3)
- Dwr (1)
- 日常使用技巧 (11)
- eclipse使用技巧 (3)
- jxl使用技巧 (3)
- Struts2 (7)
- java 报表 (3)
- Webservices (2)
- Flex (15)
- vc,vc++ (11)
- Spring (6)
- j2me开发 (1)
- Java (27)
- Sql (11)
- Javascript (5)
- extjs (0)
- C# (8)
- jQuery (2)
- PHP (3)
- apache (4)
- sso单点登录 (1)
- linux (6)
- cisco vpn (1)
- android (1)
- MongoDB性能优化 (1)
- nosql (1)
- Java netbeans (1)
- js (1)
最新评论
-
jinyanhui2008:
hzq20100521 写道你好,我的需求这个有点不一样,我的 ...
spring 多数据库支持,动态切换数据库 -
hzq20100521:
你好,我的需求这个有点不一样,我的是系统启动的时候是连接的默认 ...
spring 多数据库支持,动态切换数据库 -
lbxhappy:
那如果tree.first()一开始就是最大的呢?是不是以后e ...
从bbs中看到的问题:从大量数据中取top100,整理的思路 -
programwyh:
jinyanhui2008 写道programwyh 写道我用 ...
使用jasperreports制作报表(导出pdf excel html) -
jinyanhui2008:
programwyh 写道我用java程序写的运用Jasper ...
使用jasperreports制作报表(导出pdf excel html)
为了备份特将此新的发到博客当中以备查找。
数据库的动态切换在很多项目当中都有应用,经我查阅了多篇文档,整合思路最终成功实现数据源的动态切换功能,并稳定运行了一段时间未发现异常。
我的数据源切换时根据域名并配合spring来切换的,不同的域名访问不同的数据源,当然可以根据其他的需求进行动态切换。
首先需要配置一个过滤器来过滤域名,并动态切换数据源。
web.xml 增加如下代码:
<!-- 根据域名动态切换数据源 --> <filter> <filter-name>ServerFilter</filter-name> <filter-class>com.wfy.filter.ServerFilter</filter-class> </filter> <filter-mapping> <filter-name>ServerFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
对应写入相应的java类:
package com.wfy.filter; import java.io.File; import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; import com.wfy.multiData.SpObserver; public class ServerFilter extends HttpServlet implements Filter { private static final long serialVersionUID = 6452049924844786456L; private static FilterConfig filterConfig; public void destroy() { // TODO Auto-generated method stub } public void init(FilterConfig filterConfig) throws ServletException { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { /** * 需要在此处操作数据源,将数据源切换到新定义好的数据源当中。 */ System.out.println("request.getServerName():_"+request.getServerName()); String url = Thread.currentThread().getContextClassLoader().getResource("") + "dataSource/_"+request.getServerName()+".xml"; File f=new File(url.substring(6, url.length())); //确认数据源配置文件存在,切换数据源 if(f.exists()){ SpObserver.putSp("_"+request.getServerName()); }else{ //如果数据源配置文件不存在,使用默认数据源 SpObserver.putSp("_dataSource"); } filterChain.doFilter(request, response); } }
SpObserver类:
package com.wfy.multiData; /** * @author 金鑫 * */ public class SpObserver { private static ThreadLocal local = new ThreadLocal(); public static void putSp(String sp) { local.set(sp); } public static String getSp() { return (String)local.get(); } }
这样过滤器的设置就算完成了,下面是spring的设置
spring配置文件:
<!-- 数据库模块 初始化 --> <bean id="DynamicLoadBean" class="com.wfy.multiData.DynamicLoadBean" /> <!--可以通过他动态增加新的数据源--> <bean id="InitDataSource" class="com.wfy.init.InitDataSource"></bean> <!--配置统一数据源,将来系统中使用的数据源将从他当中获取--> <bean id="DataSource" class="com.wfy.multiData.MultiDataSource"> <property name="dataSource"> <ref bean="_dataSource" /> </property> </bean>
MultiDataSource类:
package com.wfy.multiData; import java.io.PrintWriter; import java.sql.Connection; import java.sql.SQLException; import javax.sql.DataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import com.wfy.exceptionAdvisor.BusinessException; /** * @author 金鑫 * */ public class MultiDataSource implements DataSource,ApplicationContextAware { private static final Log log = LogFactory.getLog(MultiDataSource.class); private ApplicationContext applicationContext = null; private DataSource dataSource = null; /* (non-Javadoc) * @see javax.sql.DataSource#getConnection() */ public Connection getConnection() throws SQLException { return getDataSource().getConnection(); } /* (non-Javadoc) * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String) */ public Connection getConnection(String arg0, String arg1) throws SQLException { return getDataSource().getConnection(arg0, arg1); } /* (non-Javadoc) * @see javax.sql.DataSource#getLogWriter() */ public PrintWriter getLogWriter() throws SQLException { return getDataSource().getLogWriter(); } /* (non-Javadoc) * @see javax.sql.DataSource#getLoginTimeout() */ public int getLoginTimeout() throws SQLException { return getDataSource().getLoginTimeout(); } /* (non-Javadoc) * @see javax.sql.DataSource#setLogWriter(java.io.PrintWriter) */ public void setLogWriter(PrintWriter arg0) throws SQLException { getDataSource().setLogWriter(arg0); } /* (non-Javadoc) * @see javax.sql.DataSource#setLoginTimeout(int) */ public void setLoginTimeout(int arg0) throws SQLException { getDataSource().setLoginTimeout(arg0); } public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public DataSource getDataSource(String dataSourceName){ log.debug("dataSourceName:"+dataSourceName); try{ if(dataSourceName==null||dataSourceName.equals("")){ return this.dataSource; } return (DataSource)this.applicationContext.getBean(dataSourceName); }catch(NoSuchBeanDefinitionException ex){ throw new BusinessException("没有 <name:"+dataSourceName+"> 数据源 在系统当中!"); } } public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } public DataSource getDataSource(){ String sp = SpObserver.getSp(); return getDataSource(sp); } @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { // TODO Auto-generated method stub return false; } @Override public <T> T unwrap(Class<T> iface) throws SQLException { // TODO Auto-generated method stub return null; } }
DynamicLoadBean类:
package com.wfy.multiData; import java.io.IOException; import org.springframework.beans.BeansException; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.xml.ResourceEntityResolver; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.support.AbstractXmlApplicationContext; import org.springframework.web.context.support.XmlWebApplicationContext; /** * 使用方法loadBean()向spring的beanFactory动态地装载bean,该方法的参数configLocationString等同于 * spring配置中的contextConfigLocation,同样支持诸如"/WEB-INF/ApplicationContext-*.xml"的写法。 * @author FanGang * */ public class DynamicLoadBean implements ApplicationContextAware{ private XmlWebApplicationContext applicationContext = null; public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = (XmlWebApplicationContext)applicationContext; } public XmlWebApplicationContext getApplicationContext() { return applicationContext; } /** * 向spring的beanFactory动态地装载bean * @param configLocationString 要装载的bean所在的xml配置文件位置。 */ public void loadBean(String configLocationString){ XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry)getApplicationContext().getBeanFactory()); beanDefinitionReader.setResourceLoader(getApplicationContext()); beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(getApplicationContext())); try { String[] configLocations = new String[]{configLocationString}; for(int i=0;i<configLocations.length;i++){ System.out.println(configLocations[i]); beanDefinitionReader.loadBeanDefinitions(getApplicationContext().getResources(configLocations[i])); } } catch (BeansException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
InitDataSource类(如果在系统运行的时候需要动态增加数据源的话可以调用此类来执行):
package com.wfy.init; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import com.wfy.multiData.DynamicLoadBean; public class InitDataSource implements ApplicationContextAware { private ApplicationContext applicationContext = null; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } public void init(String url){ DynamicLoadBean dynamicLoadBean = (DynamicLoadBean)this.applicationContext.getBean("DynamicLoadBean"); dynamicLoadBean.loadBean("classpath:dataSource/"+ url +".xml"); } }
这样基本数据源配置就算完成了,在系统运行当时就可以根据不同的域名(连接地址)来动态的切换数据库了。
另外我的数据源配置文件是单独保存在一个文件夹当中的,这样服务在启动的时候就会动态的去加载这些数据源了
比如:
我的数据源文件是存放处classpath:dataSource文件夹里面,
那我的文件夹下面就会有很多的类似文件名的xml文件:_192.168.234.250.xml,_dataSource.xml(必须配置,默认数据源文件),_wfyerp.gnway.net.xml,然后在系统启动的时候就会去动态加载这些文件了。
如:当我们访问的地址是:http://wfyerp.gnway.net 这个网址的时候,实际数据库访问的将会是_wfyerp.gnway.net.xml文件中的数据源。
现在贴上这些配置文件的内容:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="_wfyerp.gnway.net" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver"></property> <property name="url" value="jdbc:sqlserver://192.168.234.234:1433;databaseName=fy_erp_v6"></property> <property name="username" value="sa"></property> <property name="password" value="wfyerp2005"></property> </bean> </beans>
然后会了能让spring在启动的时候加载这些配置文件,我们需要修改web.xml文件来让他启动的时候加载他们
web.xml修改spring配置如下:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml, (classpath:dataSource/*.xml 需要新增的配置信息)</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
文件内打括号的部分为新增的配置信息,其他跟默认不改变即可。
到此我们通过spring+过滤器 来动态切换数据源的问题就得到圆满解决了。
另附样例一个,导入spring2.5的包,然后index.jsp是演示不同数据源的效果,大家稍加改用几个,需要修改的地方有:
数据库连接,已经域名地址,如我的ip地址为:192.168.234.250 所以我的数据源配置文件就包含了这个文件,然后包含了localhost文件,这样就能看出数据源切换的效果来了。
- DynamicDataSource.rar (23.4 KB)
- 下载次数: 384
评论
我写的是可行的,甚至如果你在用户请求的时候动态创建数据库连接都没问题,只要你能忍受那个速度。
我写的其实是系统启动的时候没有连接任何数据库,但是在用户访问的时候才动态分配用户去连接那个数据库。
我想你的场景是否是使用默认数据库为系统初始化一些数据然后在切换数据库呢?其实这个完全是可以实现的,在MultiDataSource里面做些改造就能实现。
不需要new一个的。
先研究下
不过我的是根据不同的客户端
访问不同的数据源.
如果这样子的话可以通过session来判断,不同的session来调用不同的数据源,因为我的项目是flex的,并不存在session这个概念,所以只能那么使用了
不过我的是根据不同的客户端
访问不同的数据源.
发表评论
-
基于JUnit测试Spring MVC的正确方法。(仅限Spring 3.2)
2013-04-25 17:57 1494Java代码 package cont ... -
关于spring aop的一些思考
2010-03-10 14:00 1908最近在考虑数据流压缩的问题,因为不想去更改程序了,所以选择使用 ... -
commons DBCP 配置参数简要说明
2009-07-31 10:04 1458commons DBCP 配置参数简要 ... -
利用Spring的AOP来配置和管理你的二级缓存(EHCache) 记录以备查询
2009-04-24 12:05 1088利用Spring的AOP来配置和管理你的二级缓存(EHCach ... -
spring 异常统一处理类
2009-02-04 13:03 2529今天睡了一觉,起来突然想上来写点关于spring的东西,说动手 ...
相关推荐
本源码以简单易懂的方式,讲述了spring动态切换数据库的原理和做法,内附有指导文件,按照说明操作,即可实现spring的数据库动态切换
为了方便大伙学习和使用springM,SpringMvc系统多数据库动态切换,完整demo直接使用,下载后配置数据库可以正常运行
Spring+Hibernate下的数据库连接动态切换
Springcloud 多数库 多数据源整合,查询动态切换数据库
spring 动态切换数据库,根据类型切换所需数据库
数据库的动态切换在很多项目当中都有应用,经我查阅了多篇文档,整合思路最终成功实现数据源的动态切换功能,并稳定运行了一段时间未发现异常。 我的数据源切换时根据域名并配合spring来切换的,不同的域名访问...
spring多数据库项目代码;用于多个数据库切换查询。标准spring项目.
SpringBoot的多数据源的动态切换项目源代码,适用于不同的用户操作不同的数据库,但是其对应的repository是一样的,可以进行http请求的动态数据源切换
springboot整合redis动态切换每个数据库,
基于springboot的多数据库动态切换,通过注解的方法切换
请自行修改com/resources/datasource.properties中数据库配置,Demo中配置的两个数据源,一个是Mysql,一个是Oracle。 运行之前请自行建立数据库的表。
Spring+SpringMvc+MybatisPlus实现多数据源切换、利用自定义Aop注解,只需要在需要切换数据库的方法上加上注解即可实现、极大避免了代码冗余。
SpringBoot整合mybatis-plus实现多数据源的动态切换且支持分页查询,案例以postgresql和oracle数据库为数据源,分别使用mybatis-plus分页插件和pagehelper分页插件实现分页查询。
针对用户需求选择访问不同的数据库,用的是spring框架,访问不同数据库但表结构相同,不同数据库表结构不一样,不用数据库有些表结构一样有些又不一样! 首先,这个方案完全是在spring的框架下解决的,数据源依然...
1. 基于Aspectj实现动态数据源...6. 实现事务内切换数据源(支持原生Spring声明式事务哟,仅此一家),并支持多数据源事务回滚(有了它除了跨服务的事务你需要考虑分布式事务,其他都不需要,极大的减少了系统的复杂程度)
完整的Demo结合了springmvc——mybatis,实现了工具类文件上传下载,结合了Redis的初步使用,并且能使用threadlocal实现数据库动态切换,很适合初建项目做参考,适合初学者使用。
一套Spring+Hibernate的多个数据库切换的源码,导入eclipse里,加入相关的包就能运行。
通过SpringAop实现多数据源的动态切换 并采用Druid连接池,可扩展继续增加数据库配置。
SpringBoot,注解实现Redis 库的切换。