zoukankan      html  css  js  c++  java
  • spring 多数据源切换

    spring配置管理多数据源,方便服务访问不同数据库时,数据源切换。多少无意,直接上代码。

    1.定义数据源key枚举值(可以直接使用字符串代替,为了代码的整洁及易读性,这里使用枚举)

    public enum DataSourceEnum {
    	anquan,
    	publ,
    	tlshow,
    }
    

    2.定义数据源持有者,切换数据源使用

    public final class DataSourceHolder {
    	private static ThreadLocal<DataSourceEnum> currentDBName = new ThreadLocal<DataSourceEnum>();
    	
    	private static DataSourceEnum DEFAULT_HASH = DataSourceEnum.anquan;
    
    	public static DataSourceEnum determineDefault() {
    		return determineDS(DEFAULT_HASH);
    	}
    
    	public static DataSourceEnum determineDS(DataSourceEnum key) {
    		currentDBName.set(key);
    		log.debug("determineDS:" + key);
    		return key;
    	}
    	
    	
    	public static DataSourceEnum getCurrentDBName() {
    		return currentDBName.get();
    	}
    }
    

    3.实现数据源路由接口

    public class DBRoutingDataSource extends AbstractRoutingDataSource {
    
    	@Override
    	protected Object determineCurrentLookupKey() {
    		return DataSourceHolder.getCurrentDBName();
    	}
    
    	@Override
    	public void setTargetDataSources(Map targetDataSources) {
    		super.setTargetDataSources(targetDataSources);
    	}
    	
    	@Override
    	public Object unwrap(Class iface) throws SQLException {
    		return null;
    	}
    
    	@Override
    	public boolean isWrapperFor(Class iface) throws SQLException {
    		return false;
    	}
    }
    

    4.定义spring 切面,在执行service方法前,切换数据源。(首先要保证spring支持注解)

    @Aspect
    @lombok.extern.log4j.Log4j
    public class DetermineAspect {
    	@Pointcut("within(com.changyou.*.service.impl.*)")
    	public void withController() {}
    
    	@Before("withController()")
    	public void beforeAdvice(JoinPoint jp) {
    		if(log.isDebugEnabled()) {
    			log.debug("Reset db router before " + jp.getSignature().getDeclaringType().getSimpleName() + "." + jp.getSignature().getName() + "()");
    		}
    		DataSourceMethod datasourceMethod = ((MethodSignature)jp.getSignature()).getMethod().getAnnotation(DataSourceMethod.class);
    		DataSourceFile datasourceFile = ((MethodSignature)jp.getSignature()).getMethod().getDeclaringClass().getAnnotation(DataSourceFile.class);
    		
    		if(datasourceMethod!=null){
    			DataSourceHolder.determineDS(datasourceMethod.value());
    		}else if(datasourceFile!=null){
    			DataSourceHolder.determineDS(datasourceFile.value());
    		}else{
    			DataSourceHolder.determineDefault();
    		}
    	}
    
    }
    

    5.spring配置数据源,使用自己实现的数据源路由类(DBRoutingDataSource 

    <!-- 配置数据源 -->
    	<bean name="dataSource_0" parent="abstractProxoolDataSource">
    		<property name="url" value="${jdbc.0.url}" />
    		<property name="username" value="${jdbc.0.username}" />
    		<property name="password" value="${jdbc.0.password}" />
    	</bean>
    	
    	<!-- 配置数据源tlshow-->
    	<bean name="dataSource_1" parent="abstractProxoolDataSource">
    		<property name="url" value="${jdbc.1.url}" />
    		<property name="username" value="${jdbc.1.username}" />
    		<property name="password" value="${jdbc.1.password}" />
    	</bean>
    	
    	<!-- 配置数据源publicaccount-->
    	<bean name="dataSource_2" parent="abstractProxoolDataSource">
    		<property name="url" value="${jdbc.2.url}" />
    		<property name="username" value="${jdbc.2.username}" />
    		<property name="password" value="${jdbc.2.password}" />
    	</bean>
    	
    	
    	<bean id="dataSource" class="com.changyou.common.util.dbaccess.DBRoutingDataSource">
    		<property name="defaultTargetDataSource" ref="dataSource_0"/>
    		<property name="targetDataSources">
    			<map key-type="com.changyou.common.enums.DataSourceEnum"><!-- 数据源枚举 -->
    				<entry key="anquan" value-ref="dataSource_0" />
    				<entry key="tlshow" value-ref="dataSource_1" />
    				<entry key="publ" value-ref="dataSource_2" />
    			</map>
    		</property>
    	</bean>
    

    6.基础工作完成,下面开始使用,需要在server类或方法上添加注解。(上面的切面会查看是否有指定注解的存在)。

      定义自己的注解:

    @Target(value={ElementType.TYPE,ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DataSourceRouter {
    	public DataSourceEnum value() default DataSourceEnum.anquan;
    }
    

    7.开始愉快的使用吧,方法上的注解权限高于整个类上的注解,这取决于切面的处理方式。

    @Service
    @DataSourceRouter(DataSourceEnum.publ)
    public class CyjUserServiceImpl{
    
    	@Autowired
    	private UserMapper userMapper;
    	
    	public void saveOrUpdateBlock(CyjUserBlock cyjUserBlock) {
    		userMapper.saveOrUpdateBlock(cyjUserBlock);
    	}
    
            @DataSourceRouter(DataSourceEnum.anquan)
    	public void deleteBlockById(int blockId) {
    		userMapper.deleteBlockById(blockId);
    	}
    }
    

      

    ok,后期补上demo。。。。。。。

  • 相关阅读:
    BZOJ 3132: 上帝造题的七分钟 树状数组+差分
    PAT Advanced 1006 Sign In and Sign Out (25 分)
    PAT Advanced 1011 World Cup Betting (20 分)
    PAT Basic 1032 挖掘机技术哪家强 (20 分)
    PAT Basic 1028 人口普查 (20 分)
    PAT Basic 1004 成绩排名 (20 分)
    大数据数据库HBase(二)——搭建与JavaAPI
    PAT Advanced 1009 Product of Polynomials (25 分)(vector删除元素用的是erase)
    PAT Advanced 1002 A+B for Polynomials (25 分)(隐藏条件,多项式的系数不能为0)
    PAT Basic 1041 考试座位号 (15 分)
  • 原文地址:https://www.cnblogs.com/rmsSpring/p/5405403.html
Copyright © 2011-2022 走看看