- 浏览: 320918 次
- 性别:
- 来自: 青岛
文章分类
- 全部博客 (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:
<div class="quote_title ...
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 1558Java代码 package cont ... -
关于spring aop的一些思考
2010-03-10 14:00 1947最近在考虑数据流压缩的问题,因为不想去更改程序了,所以选择使用 ... -
commons DBCP 配置参数简要说明
2009-07-31 10:04 1509commons DBCP 配置参数简要 ... -
利用Spring的AOP来配置和管理你的二级缓存(EHCache) 记录以备查询
2009-04-24 12:05 1132利用Spring的AOP来配置和管理你的二级缓存(EHCach ... -
spring 异常统一处理类
2009-02-04 13:03 2576今天睡了一觉,起来突然想上来写点关于spring的东西,说动手 ...
相关推荐
总之,Spring的数据库动态切换功能通过抽象化DataSource路由,实现了在运行时根据业务逻辑或环境条件灵活切换数据库的能力。这一特性大大增强了应用程序的灵活性和可扩展性。通过深入学习和实践,你可以将其应用于...
在Spring MVC和Spring Data JPA框架中,实现多数据库动态切换是一项常见的需求,尤其是在大型分布式系统中。这个压缩包提供了一个完整的示例(demo),帮助开发者理解和应用这一功能。下面将详细讲解如何在Spring...
在开发多租户或多数据库环境的应用系统时,往往需要实现动态切换数据库连接的功能。本文档将详细探讨如何在Spring与Hibernate框架下实现数据库连接的动态切换。该功能允许用户在登录时选择或输入特定的数据库名称,...
总的来说,Spring Cloud多数据源整合和动态切换数据库是一项挑战性的工作,但通过合理的架构设计和Spring框架的特性,可以有效地实现这一功能,为大型分布式系统提供灵活和可扩展的数据访问能力。
在Spring框架中,动态切换数据库是一项重要的功能,它允许应用程序根据特定条件或需求在运行时灵活地连接到不同的数据库。这种能力在多租户环境、数据隔离或测试环境中尤其有用。接下来,我们将深入探讨实现这一功能...
数据库的动态切换在很多项目当中都有应用,经我查阅了多篇文档,整合思路最终成功实现数据源的动态切换功能,并稳定运行了一段时间未发现异常。 我的数据源切换时根据域名并配合spring来切换的,不同的域名访问...
在多数据库切换查询中,`@Profile`注解可以帮助我们在不同环境(如开发、测试、生产)之间切换数据库配置。例如,你可以为每个环境创建一个配置类,并用`@Profile("dev")`、`@Profile("test")`和`@Profile("prod")`...
在Spring Boot应用中,数据库连接动态切换是一种常见的需求,尤其在多租户或者有不同业务场景的系统中。本项目提供了实现这一功能的源代码,允许根据不同的用户操作或HTTP请求来选择不同的数据库,而无需修改...
在Spring Boot应用中,动态连接多数据库是一种常见的需求,尤其在构建分布式系统或者需要支持多种数据源的场景下。Spring Boot以其简洁的配置和强大的自动配置能力,使得处理这种复杂性变得相对简单。本篇文章将深入...
然而,在某些情况下,我们可能需要在运行时根据不同的条件或需求动态地切换数据库,比如在测试环境和生产环境中使用不同的数据库。这个过程就称为“动态切换数据库”。在本文中,我们将深入探讨如何在Java Hibernate...
springboot整合redis动态切换每个数据库,
这可以通过监听数据库表的变化,获取最新的数据源配置,然后通过Spring的`DataSourceProxy`或`AbstractRoutingDataSource`实现动态数据源切换。 3. **数据库方言动态切换** Sharding-JDBC支持多种数据库,如MySQL...
在现代企业级应用开发中,...通过配置不同的数据源、自定义注解和AOP切面,我们可以轻松地实现在运行时动态切换数据库,满足各种复杂业务需求。在实际开发中,还需要考虑性能优化、错误处理和代码的可维护性等因素。
"Spring多数据源动态切换方案"是解决这一问题的关键技术,它允许应用程序根据业务需求动态选择数据源,提高了系统的灵活性和可扩展性。下面我们将详细探讨如何在Spring中实现多数据源的配置及动态切换。 首先,我们...
在IT行业中,Spring.Net和NHibernate是两个非常重要的开源框架,...你可以根据实际需求调整数据库配置、SessionFactory设置,以及业务逻辑中的数据库切换逻辑,确保应用程序能够高效、稳定地运行在多种数据库环境之下。
在IT行业中,构建大型分布式系统时,数据源的动态切换是一项关键能力,它允许系统根据业务需求选择不同的数据库进行操作。本项目“Spring+SpringMvc+MybatisPlus+Aop(自定义注解)动态切换数据源”正是针对这一需求...
这通常在多租户系统、数据隔离或者需要在不同环境(如开发、测试、生产)之间切换数据库的情况下非常有用。本项目提供了一套完整的源代码实现,帮助开发者理解并应用这一技术。 首先,Spring Boot通过`spring-boot-...
在进行JEECG切换数据库时,支持多种主流数据库系统,例如ORACLE、MySQL和Microsoft SQL Server等。下面将详细阐述JEECG平台切换数据库的具体操作步骤及其背后涉及的相关知识点。 首先,了解数据库配置文件的重要性...
在实际项目中,我们可能需要根据特定的条件动态切换数据库。这时,可以创建一个工具类,提供一个方法接收数据库编号,并返回对应的`RedisTemplate`: ```java @Component public class RedisUtil { @Autowired ...