目前项目框架很简单,spring+spring jdbc。
客户想,
1,临时添加一个数据源,然后切换到此数据源,进行操作。
2,能保证每个数据源的表结构是统一的。
解决思路,spring jdbc用到的是jdbctemplate, jdbctemplate需要一个datasource。实现一个datasource,
把“判断连接哪个数据源”的条件存在 ThreadLocal 中,这样在自己的datasource里,就可以取出来使用。而不用
在service和dao中该代码了。
1,在controller层中切换数据源。根据id在一个固定数据源()中查找已经储存的数据源信息,把需要切换的数据源和当前登录用户绑定起来(这里自己任意实现)。
public String changeDBSource(){
if( !StringUtils.isBlank(id) ){
dbSource = databaseSourceService.findDBSourceById(id);
boolean b = false;
if(b){
//用户登录情况下,把dbSource与用户绑定。
}else{
//没有登录的情况下
ActionContext.getContext().getSession().put(DatabaseObserver.DBKEY, dbSource);
}
DatabaseObserver.put(dbSource);
}
if( StringUtils.isBlank(dbSource.getId())){
flag = "0";
}else{
flag = "1";
}
return "changeResult";
}
附上DatabaseObserver的代码,很简单
public class DatabaseObserver {
public static final String DBKEY = "dbkey";
private static ThreadLocal <DatabaseSource> dbSource = new ThreadLocal<DatabaseSource>();
public static void put (DatabaseSource dbs)
{
dbSource.set(dbs);
}
public static DatabaseSource get ()
{
return (DatabaseSource)dbSource.get();
}
}
2,与用户绑定后,用一个Filter过滤所有请求,把与用户绑定的数据源信息,通过DatabaseObserver写到ThreadLocal中。
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 {
boolean b = false;
//如果用户登录了,则把数据源信息与用户绑定
HttpServletRequest httpRequest = (HttpServletRequest)request;
if(b==true){
}
else{
//没有登录的情况下
DatabaseSource dbSource = (DatabaseSource)httpRequest.getSession().getAttribute(DatabaseObserver.DBKEY);
if(dbSource!=null){
DatabaseObserver.put(dbSource);
}
}
filterChain.doFilter(request, response);
}
}
3,最后在自己实现的datasource中,根据Threadlocal的数据源信息,返回的datasource。
public class DataSourceWithCache implements DataSource {
private static Map<String, DataSource> sources = new HashMap<String, DataSource>();
@Resource
private IDatabaseSourceService databaseSourceService ;
private DataSource getDataSource() {
DatabaseSource dbSource = DatabaseObserver.get();
if( dbSource == null ){
List<DatabaseSource> dbList = databaseSourceService.findBDSourcesByCond(dbSource, 0 , 1);
if(dbList.size()>0){
dbSource = dbList.get(0);
}
if( dbSource == null ){
return null;
}
}
DataSource source = sources.get(dbSource.getId());
if (source == null) {
source = createSource(dbSource);
sources.put(dbSource.getId(), source);
}
return source;
}
private DataSource createSource( DatabaseSource dbSource ) {
SingleConnectionDataSource source = new SingleConnectionDataSource();
source.setDriverClassName("com.mysql.jdbc.Driver");
source.setUrl(dbSource.getUrl());
source.setUsername(dbSource.getUsername());
source.setPassword(dbSource.getPassword());
source.setSuppressClose(true);
return source;
}
@Override
public Connection getConnection() throws SQLException {
return getDataSource().getConnection();
}
@Override
public Connection getConnection(String username, String password)
throws SQLException {
return getDataSource().getConnection(username, password);
}
@Override
public PrintWriter getLogWriter() throws SQLException {
return getDataSource().getLogWriter();
}
@Override
public int getLoginTimeout() throws SQLException {
return getDataSource().getLoginTimeout();
}
@Override
public void setLogWriter(PrintWriter out) throws SQLException {
getDataSource().setLogWriter(out);
}
@Override
public void setLoginTimeout(int seconds) throws SQLException {
getDataSource().setLoginTimeout(seconds);
}
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return getDataSource().isWrapperFor(iface);
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
return getDataSource().unwrap(iface);
}
public IDatabaseSourceService getDatabaseSourceService() {
return databaseSourceService;
}
public void setDatabaseSourceService(IDatabaseSourceService databaseSourceService) {
this.databaseSourceService = databaseSourceService;
}
}
分享到:
相关推荐
使用注解配置实现Spring动态数据源切换,实现原理 1、自定义动态数据源类DynamicDataSource: 实现spring类AbstractRoutingDataSource的方法determineCurrentLookupKey 2、自定义Spring AOP类DataSourceAspect 3、...
mybatis+spring实现动态切换数据源,修改数据源配置信息之后,直接运行test可进行测试
请自行修改com/resources/datasource.properties中数据库配置,Demo中配置的两个数据源,一个是Mysql,一个是Oracle。 运行之前请自行建立数据库的表。
spring 动态切换数据源
1. 基于Aspectj实现动态数据源切换,支持类级、方法级,方法级优先于类级 2. 实现数据源动态注册、修改、删除,无需重启服务 3. 实现同时兼容多种数据源连接池 4. 实现动态数据源连接池属性配置 5. 采用双端队列实现...
个人博文----真正意义的spring动态切换数据源 对应的源码,使用spring+springmvc+mybatis开发
用于详细描述配置spring下多数据源动态切换方案的实施配置说明。可以自动切换数据源的配置。
Spring+SpringMvc+MybatisPlus实现多数据源切换、利用自定义Aop注解,只需要在需要切换数据库的方法上加上注解即可实现、极大避免了代码冗余。
spring boot mybatis plus 多数据源切换的demo解压运行
spring mybatis 多数据源动态切换
通过SpringAop实现多数据源的动态切换 并采用Druid连接池,可扩展继续增加数据库配置。
通过简单的demo实现SpingBoot多数据源配置并动态切换多数据源
mybatis+spring实现动态切换数据源,修改数据源配置信息之后,直接运行test可进行测试 maven项目 导入即可 jar包都不用 适合学习参考 出自Java自学网 (Java自学网专供 就是免积分下载)
Spring 动态切换 数据源 可同事在多个数据源中切换
本篇文章主要介绍了详解Spring(AbstractRoutingDataSource)实现动态数据源切换,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
Springcloud 多数库 多数据源整合,查询动态切换数据库
spring boot整合druid连接池,采用注解方式实现多数据源动态切换 jdk版本1.8 spring boot版本1.5.14
一个spring boot动态切换多数据源的完整demo。
spring+druid+AtomikosDataSource实现多数据源切换及分布式事务控制
java spring 多数据源目前版本为mysql版本 利用spring aop 切面,自动切换数据源。