springboot+mybatis配置多数据源+aop动态数据源切换
最近告诉项目需要做多数据源得配置,鼓捣了很久,一直没有做aop得数据源切换,一直只能调用默认得是具有,在网上找了一些资料进行了配置,项目能够成功得进行数据源得切换,把心得保存下来和大家分享一下。
1.数据库多数据源配置
2.自定义一个数据源配置类DataSourceConfigurer
@Configuration public class DataSourceConfigurer { //主数据源 @Bean(name = "writingDataSource") /* @Qualifier("writingDataSource")*/ @ConfigurationProperties(prefix ="spring.datasource.writing") /*@Primary//配置该数据源为主数据源*/ public DataSource writingDataSource(){return DataSourceBuilder.create().build();} //从数据源 @Bean(name = "userDataSource")//装配该方法返回值为userDataSource管理bean /* @Qualifier("userDataSource")*///spring装配bean唯一标识 @ConfigurationProperties(prefix="spring.datasource.user")//application.yml文件内配置数据源的前缀 public DataSource userDataSource(){return DataSourceBuilder.create().build();} @Primary//设置默认数据源 @Bean(name = "dynamicDataSource") public DataSource dynamicDataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); // 默认数据源 dynamicDataSource.setDefaultTargetDataSource(writingDataSource()); // 配置多数据源 Map<Object, Object> dsMap = new HashMap(); dsMap.put("writingDataSource", writingDataSource()); dsMap.put("userDataSource", userDataSource()); dynamicDataSource.setTargetDataSources(dsMap); return dynamicDataSource; } /** * 配置@Transactional注解事物 * @return */ @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dynamicDataSource()); }
3.创建一个类DynamicDataSource获取数据源名
public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { System.out.println("数据源为"+DataSourceContextHolder.getDB()); return DataSourceContextHolder.getDB(); } }
4.创建DataSourceContextHolder类,对数据源进行操作。
public class DataSourceContextHolder { /** * 默认数据源 */ public static final String DEFAULT_DS = "writingDataSource"; private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); // 设置数据源名 public static void setDB(String dbType) { System.out.println("切换到{"+dbType+"}数据源"); contextHolder.set(dbType); } // 获取数据源名 public static String getDB() { return (contextHolder.get()); } // 清除数据源名 public static void clearDB() { contextHolder.remove(); } }
5.自定义一个注解(@DC)
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface DS { String value() default "writingDataSource"; }
6.动态切换数据源DynamicDataSourceAspect类
@Aspect @Component public class DynamicDataSourceAspect { @Before("@annotation(DS)") public void beforeSwitchDS(JoinPoint point){ //获得当前访问的class Class<?> className = point.getTarget().getClass(); //获得访问的方法名 String methodName = point.getSignature().getName(); //得到方法的参数的类型 Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes(); String dataSource = DataSourceContextHolder.DEFAULT_DS; try { // 得到访问的方法对象 Method method = className.getMethod(methodName, argClass); // 判断是否存在@DS注解 if (method.isAnnotationPresent(DS.class)) { DS annotation = method.getAnnotation(DS.class); // 取出注解中的数据源名 dataSource = annotation.value(); } } catch (Exception e) { e.printStackTrace(); } // 切换数据源 DataSourceContextHolder.setDB(dataSource); } @After("@annotation(DS)") public void afterSwitchDS(JoinPoint point){ DataSourceContextHolder.clearDB(); } }
7配置完成之后调用controller层里面得方法,在serviceImpl得方法中加上注解,确定调用得是哪个数据库,
@DS("writingDataSource")租借表示调用得是writingDataSource数据源
@Override @DS("writingDataSource") public Message excellentList(Message message) { List<TbWorks> list=tbWorksMapper.excellentList(); PageInfo pageInfo = new PageInfo(list); message.setData(pageInfo); message.setCode("200"); message.setMsg("查询成功"); return message; }