1. 程式人生 > 其它 >spring動態資料來源實現(通過包名動態設定資料來源)

spring動態資料來源實現(通過包名動態設定資料來源)

通過建立資料來源掃描類可以建立多資料來源,但是每新增一個數據源就要相應的實現,遂想根據包路徑自動選擇相應的資料來源 最終效果: 如設定spring.datasource.one.url = xxx,然後mapper類寫在one包下如com.mutool.one.mapper.TestMapper即可

設定預設資料來源和可選資料來源

@Slf4j
@Component
public class DynaCachedDataSource extends AbstractRoutingDataSource implements EnvironmentAware {

   private Environment environment;

   boolean hasInit = false;

   String validationQuerySql = "select 1";// 驗證連線是否成功的sql

   public DynaCachedDataSource() {
      
super(); super.setTargetDataSources(new HashMap()); } @Override public void setEnvironment(Environment environment) { this.environment = environment; } @Override public Connection getConnection() throws SQLException { if (!hasInit) { initDateSourceByProperties(); }
return super.getConnection(); } /** * 初始化配置 */ private void initDateSourceByProperties() { String driver = environment.getProperty("spring.datasource.driver-class-name"); String url = environment.getProperty("spring.datasource.url"); String username = environment.getProperty("spring.datasource.username"); String password
= environment.getProperty("spring.datasource.password"); DruidDataSource defaultDS = new DruidDataSource(); defaultDS.setDriverClassName(driver); defaultDS.setUrl(url); defaultDS.setUsername(username); defaultDS.setPassword(password); defaultDS.setValidationQuery(validationQuerySql); //其他屬性自行設定 this.setDefaultTargetDataSource(defaultDS); this.setTargetDataSources(getTargetsMap()); super.afterPropertiesSet(); hasInit = true; } private Map<Object, Object> getTargetsMap() { Map<Object, Object> targets = new HashMap<Object, Object>(); Map<String, Map<String, String>> datasourceGroupMap = getDatasourceConfig(); datasourceGroupMap.forEach((k, v) -> { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName(v.get("spring.datasource."+k+".driver-class-name")); dataSource.setUrl(v.get("spring.datasource."+k+".url")); dataSource.setUsername(v.get("spring.datasource."+k+".username")); dataSource.setPassword(v.get("spring.datasource."+k+".password")); dataSource.setValidationQuery(validationQuerySql); //其他屬性自行設定 targets.put(k, dataSource); }); return targets; } @Override protected Object determineCurrentLookupKey() { return getDataSource(); } // 執行緒本地環境 private static final ThreadLocal<String> dataSources = new ThreadLocal<String>(); // 設定資料來源 public static void setDataSource(String customerType) { dataSources.set(customerType); } // 獲取資料來源 public static String getDataSource() { return dataSources.get(); } /** * 從spring配置中獲取全部資料來源配置 * @return */ private Map<String, Map<String, String>> getDatasourceConfig(){ Map<String, Map<String, String>> datasorceGroupMap = new HashMap<>(); StandardServletEnvironment standardServletEnvironment = (StandardServletEnvironment) environment; Iterator<PropertySource<?>> iterator = standardServletEnvironment.getPropertySources().iterator(); while (iterator.hasNext()) { PropertySource<?> source = iterator.next(); Object o = source.getSource(); if (o instanceof Map) { for (Map.Entry<String, Object> entry : ((Map<String, Object>) o).entrySet()) { String key = entry.getKey(); //判斷如果以spring.datasource開始的配置取出 if(!key.startsWith("spring.datasource")){ continue; } String value = standardServletEnvironment.getProperty(key); String datasourceGroup = ReUtil.getGroup1("datasource\\.(.*?)\\.", value); if(StrUtil.isBlank(datasourceGroup)){ datasourceGroup = "default"; } Map<String, String> datasourceConfigMap = datasorceGroupMap.get(datasourceGroup); if(datasourceConfigMap == null){ datasourceConfigMap = new HashMap<>(); datasorceGroupMap.put(datasourceGroup, datasourceConfigMap); } datasourceConfigMap.put(key, value); } } } return datasorceGroupMap; } }

動態選擇資料來源

@Slf4j
@Component
@Aspect
public class DynaDataSourceInterceptor {
   
   @Before("execution(* com.mutool..mapper.*Mapper.*(..))")
    public void dynamicSetDataSoruce(JoinPoint joinPoint) throws Exception {
      Object target = joinPoint.getTarget();
      Class<?> clazz = target.getClass();
      String className = clazz.getName();
      if(Proxy.isProxyClass(target.getClass())) {
         Type[] types = AopUtils.getTargetClass(target).getGenericInterfaces();
         className = types[0].getTypeName();
      }
      if(!className.contains(".mapper.")){
         log.error("資料來源切面攔截解析包路徑錯誤,解析得到類名:{}", className);
         return;
      }
      String pkg = className.substring(0, className.indexOf(".mapper."));
      pkg = pkg.substring(pkg.lastIndexOf('.') + 1);
      if (pkg.equals("mybatis")) {
         Thread.sleep(1000);
      }
      DynaCachedDataSource.setDataSource(pkg);
   }
}