spring boot 註解方式配置多資料來源與使用
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/xujl?useUnicode=true&characterEncoding=UTF-8
url: jdbc:postgresql://172.xx.x.xx:xxxx/pcsu?charSet=utf-8
username: suit_test
driverClassName: org.postgresql.Driver
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
#login-password: admin
上面的方式實現就已經配置了兩個 資料來源了,下面來看下程式碼的實現
2、配置一個註解,方便使用,直接在需要配置的方法上面加上資料來源即可
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
- /**
- * 增加多資料來源,在此配置
- */
- public interface DataSourceNames {
- String FIRST = "first";
- String SECOND = "second";
- }
- /**
- * 動態資料來源
- */
- public class DynamicDataSource extends AbstractRoutingDataSource {
- //用來儲存資料來源與獲取資料來源
- private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
- public DynamicDataSource(DataSource defaultTargetDataSource, Map<String, DataSource> targetDataSources) {
- super.setDefaultTargetDataSource(defaultTargetDataSource);
- super.setTargetDataSources(new HashMap<Object, Object>(targetDataSources));
- super.afterPropertiesSet();
- }
- @Override
- protected Object determineCurrentLookupKey() {
- return getDataSource();
- }
- public static void setDataSource(String dataSource) {
- contextHolder.set(dataSource);
- }
- public static String getDataSource() {
- return contextHolder.get();
- }
- public static void clearDataSource() {
- contextHolder.remove();
- }
- }
這裡有必要說一下AbstractRoutingDataSource這個類,載入一個圖片:
可以看到AbstractRoutingDataSource獲取資料來源之前會先呼叫determineCurrentLookupKey方法查詢當前的lookupKey,這個lookupKey就是資料來源標識。
因此通過重寫這個查詢資料來源標識的方法就可以讓spring切換到指定的資料來源了。
(這張圖片出自:點選開啟連結 尊重原創。)
- /**
- * 配置多資料來源
- */
- @Configuration
- public class DynamicDataSourceConfig {
- @Bean
- @ConfigurationProperties("spring.datasource.druid.first")
- public DataSource firstDataSource(){
- return DruidDataSourceBuilder.create().build();
- }
- @Bean
- @ConfigurationProperties("spring.datasource.druid.second")
- public DataSource secondDataSource(){
- return DruidDataSourceBuilder.create().build();
- }
- @Bean
- @Primary
- public DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource) {
- Map<String, DataSource> targetDataSources = new HashMap<>();
- targetDataSources.put(DataSourceNames.FIRST, firstDataSource);
- targetDataSources.put(DataSourceNames.SECOND, secondDataSource);
- return new DynamicDataSource(firstDataSource, targetDataSources);
- }
- }
4、最最重要的一步,就是使用spring的aop原理,切面方式載入資料來源
- /**
- * 多資料來源,切面處理類 處理帶有註解的方法類
- */
- @Aspect
- @Component
- public class DataSourceAspect implements Ordered {
- protected Logger logger = LoggerFactory.getLogger(getClass());
- @Pointcut("@annotation(xxxx.DataSource)")//注意:這裡的xxxx代表的是上面public @interface DataSource這個註解DataSource的包名
- public void dataSourcePointCut() {
- }
- @Around("dataSourcePointCut()")
- public Object around(ProceedingJoinPoint point) throws Throwable {
- MethodSignature signature = (MethodSignature) point.getSignature();
- Method method = signature.getMethod();
- DataSource ds = method.getAnnotation(DataSource.class);
- if (ds == null) {
- DynamicDataSource.setDataSource(DataSourceNames.FIRST);
- logger.debug("set datasource is " + DataSourceNames.FIRST);
- } else {
- DynamicDataSource.setDataSource(ds.name());
- logger.debug("set datasource is " + ds.name());
- }
- try {
- return point.proceed();
- } finally {
- DynamicDataSource.clearDataSource();
- logger.debug("clean datasource");
- }
- }
- @Override
- public int getOrder() {
- return 1;
- }
- }
5、最後一步就是使用了在你的service的實現類 serviceImpl上面進行註解,這裡是重點(我剛開一直放在dao上面,因為我用的是mybatis,以為就是要放在這個上面,結果一直出不來,最後才知道應該放在serviceImpl上面)@Override
- @DataSource(name="second")
- public List<IntegralExchangeRule> list(Map<String,Object> map) {
- return dao.list(map);
- }
有必要說一下:我上面的DataSourceAspect這個類裡面around方法裡面,已經預設是資料來源1,如果你不配置@DaeSource(name=""),它預設會使用第一個資料來源,否則的話,按照你的資料來源名稱去使用的。;
**歡迎關注我的個人公眾號:we-aibook,裡面有相關技術文章分享,專案架構,知識星球,技術交流群,不定期進行抽獎送書活動喲!**