记录⼀下java开发中多数据源的配置过程,1.配置⽂件application.yml
personnel:#数据源1
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3307/person?useSSL=false&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&allowMultiQueries=true&allowPublicKey username: root password: ******* userauth:#数据源2
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://localhost:3307/user?useSSL=false&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC&allowMultiQueries=true&allowPublicKeyR username: root password: ******
2.不同数据源枚举:
public enum DataSourceEnum {master,slaver;}3.枚举类⼯具 set
public class DataSourceContextHolder {
private static final ThreadLocal @Override protected DataSourceEnum initialValue() { return DataSourceEnum.master; } }; public static void setDataSourceType(DataSourceEnum type) { CONTEXT_HOLDER.set(type); } public static DataSourceEnum getDataSourceType() { return CONTEXT_HOLDER.get(); } public static void resetDataSourceType() { CONTEXT_HOLDER.set(DataSourceEnum.master); }} 4.⾃定义注解 @Retention(RetentionPolicy.RUNTIME) // 在运⾏时可见@Target(ElementType.METHOD) // 注解可以⽤在⽅法上 public @interface DataSourceTypeAnno { //使⽤⽅式在service层⽅法上添加@DataSourceTypeAnno(DataSourceEnum.数据源枚举类型)⽤于指定所使⽤的数据源DataSourceEnum value() default DataSourceEnum.master; } 5.aop拦截:这⾥使⽤asp的 import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Pointcut;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component; import java.lang.reflect.Method; @Component@Aspect @Order(-100)//为了保证可以拦截到public class DataSourceAspect { @Pointcut(\"execution(* com.yzy.*.*..*(..)) \" + //这⾥扫描的切点包是主要是service层,根据service层⽅法的上边所说的的⾃定义注解,去判断所使⽤的数据源类型,并动态切换数据源 \"&& @annotation(com.yzy.config.DataSourceTypeAnno)\") public void dataSourcePointcut() { } @Around(\"dataSourcePointcut()\") public Object doAround(ProceedingJoinPoint pjp) { MethodSignature methodSignature = (MethodSignature) pjp.getSignature(); Method method = methodSignature.getMethod(); DataSourceTypeAnno typeAnno = method.getAnnotation(DataSourceTypeAnno.class); DataSourceEnum sourceEnum = typeAnno.value(); if (sourceEnum == DataSourceEnum.master) { DataSourceContextHolder.setDataSourceType(DataSourceEnum.master); } else if (sourceEnum == DataSourceEnum.slaver) { DataSourceContextHolder.setDataSourceType(DataSourceEnum.slaver); } Object result = null; try { result = pjp.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } finally { DataSourceContextHolder.resetDataSourceType(); } return result; }} 6.继承 AbstractRoutingDataSource 类,实现对应数据源key的切换 package com.yzy.config; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class DynamicDataSource extends AbstractRoutingDataSource { protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSourceType(); }} 7.配置mybatisConfig=》数据源信息 import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.jdbc.DataSourceBuilder;//org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;该包在springboot2.0被取代,⽬前⽹上的都是这个springboot1.5的包,所以会⼀直报错import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource;import java.util.HashMap;import java.util.Map; @Configuration @MapperScan(basePackages = \"com.yzy.*.mapper\")//扫描dao层mapper接⼝public class MyBatisConfig { /** * @return * @throws Exception * @Primary 必需指定⼀个且只能有⼀个主数据源,否则报错 */ @Primary @Bean(\"masterDataSource\") @ConfigurationProperties(prefix = \"spring.datasource.userauth\")//根据数据源前缀到application.yml读取数据源信息//此处改变前缀可以改变默认数据源// public DataSource masterDataSource() throws Exception { return DataSourceBuilder.create().build(); } @Bean(\"slaverDataSource\") @ConfigurationProperties(prefix = \"spring.datasource.personnel\")//根据数据源前缀到application.yml读取数据源信息//可以配置更多数据源,到前提是application.yml中存在,⽽且也需要在枚举类中添加枚举类型 public DataSource slaverDataSource() throws Exception { return DataSourceBuilder.create().build(); } /** * @Qualifier 根据名称进⾏注⼊,通常是在具有相同的多个类型的实例的⼀个注⼊(例如有多个DataSource类型的实例) * @DataSourceTypeAnno(DataSourceEnum.master)事务⽅法需要指定数据源 */ @Bean(\"dynamicDataSource\") public DynamicDataSource dynamicDataSource(@Qualifier(\"masterDataSource\") DataSource masterDataSource, @Qualifier(\"slaverDataSource\") DataSource slaverDataSource) { Map