1.yml配置:
spring: datasource: his: driver-class-name: com.mysql.cj.jdbc.Driver password: aa jdbc-url: jdbc:mysql://aa:3306/aa?useUnlcode=1&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&remarksReporting=true&serverTimezone=GMT%2B8 username: aa gym: driver-class-name: com.mysql.cj.jdbc.Driver password: bb jdbc-url: jdbc:mysql://bb/bb?useUnlcode=1&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&remarksReporting=true&serverTimezone=GMT%2B8 username: bb
package com.gymexpress.histar.config;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.boot.jdbc.DataSourceBuilder;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;import java.util.HashMap;import java.util.Map;2.多数据源配置类
/** * @author * 多数据源配置类 */@Configurationpublic class DataSourceConfig { /** * 数据源exgym_new * @return */ @Bean(name="dataSourceHis") @ConfigurationProperties(prefix = "spring.datasource.his") public DataSource dataSourceHis(){ return DataSourceBuilder.create().build(); } /** * 数据源gym * @return */ @Bean(name="dataSourceGym") @ConfigurationProperties(prefix = "spring.datasource.gym") public DataSource dataSourceGym(){ return DataSourceBuilder.create().build(); } /** * 动态数据源:通过aop在不同的数据源之间动态切换 * @return */ @Primary @Bean(name="dynamicDataSource") public DataSource dynamicDataSource(){ DynamicDataSource dynamicDataSource=new DynamicDataSource(); //默认数据源 dynamicDataSource.setDefaultTargetDataSource(dataSourceHis()); //配置多数据源 Map<Object,Object> dsMap=new HashMap<>(); dsMap.put("dataSourceHis",dataSourceHis()); dsMap.put("dataSourceGym",dataSourceGym()); dynamicDataSource.setTargetDataSources(dsMap); return dynamicDataSource; } /** * 配置@transactional注解事务 * @return */ @Bean public PlatformTransactionManager transactionManager(){ return new DataSourceTransactionManager(dynamicDataSource()); }}3.配置默认数据源
package com.gymexpress.histar.config;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class DataSourceContextHolder { private static final Logger LOGGER= LoggerFactory.getLogger(DataSourceContextHolder.class); /** * 默认数据源 */ public static final String DEFAULT_DS="dataSourceHis"; /** * 当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本, * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 */ private static final ThreadLocal<String> contextHolder=new ThreadLocal<>(); /** * 设置数据库名 * @param dbType */ public static void setDB(String dbType){ LOGGER.info("切换到{"+dbType+"}数据源"); contextHolder.set(dbType); } /** * 获取数据源名 * @return */ public static String getDB(){ return (contextHolder.get()); } /** * 清楚数据源 */ public static void clearDB(){ contextHolder.remove(); }}4.自定义注解
package com.gymexpress.histar.config;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * @author * 自定义注解 */@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface DS { /** * 默认His数据库 * @return */ String value() default "dataSourceHis";}
5.获取数据源
package com.gymexpress.histar.config;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/** * @author * */public class DynamicDataSource extends AbstractRoutingDataSource { private static final Logger LOGGER= LoggerFactory.getLogger(DynamicDataSource.class); @Override protected Object determineCurrentLookupKey() { LOGGER.info("数据源为:"+DataSourceContextHolder.getDB()); return DataSourceContextHolder.getDB(); }}6.切换数据源
package com.gymexpress.histar.config;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.reflect.MethodSignature;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import java.lang.reflect.Method;/** * 自定义注解 + AOP的方式实现数据源动态切换。 * @author * */@Aspect@Componentpublic class DynamicDataSourceAspect { private static final Logger LOGGER= LoggerFactory.getLogger(DynamicDataSourceAspect.class); @Before("@annotation(DS)") public void beforeSwitchDS(JoinPoint point){ //获得当前访问的class Class<?> className = point.getTarget().getClass(); //获得访问的方法名 String name = point.getSignature().getName(); //得到方法参数的类型 Class[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes(); String datasource = DataSourceContextHolder.DEFAULT_DS; try { //得到访问的方法对象 Method method = className.getMethod(name, parameterTypes); //判断是否存在@DS注解 if(method.isAnnotationPresent(DS.class)){ DS annotation = method.getAnnotation(DS.class); //取出注解中的数据源名 datasource = annotation.value(); } }catch (Exception e){ LOGGER.error(e.toString(),e); } //切换数据源 DataSourceContextHolder.setDB(datasource); } @After("@annotation(DS)") public void afterSwitchDs(JoinPoint joinPoint){ DataSourceContextHolder.clearDB(); }}