1. 程式人生 > 實用技巧 >springboot實現讀寫分離

springboot實現讀寫分離

配置:

application.yml

spring:
  datasource:
    ####寫資料來源
    update:
      jdbc-url: jdbc:mysql://192.168.100.150:8066/test
      driver-class-name: com.mysql.jdbc.Driver
      username: root
      password: root
    ###讀資料來源
    select:
      jdbc-url: jdbc:mysql://192.168.100.150:8066/test
      driver-class-name: com.mysql.jdbc.Driver
      username: user
      password: user
    type: com.alibaba.druid.pool.DruidDataSource

 

配置讀寫資料來源:

DataSourceConfig.java

/**
 * 配置讀寫資料來源
 */
@Configuration
public class DataSourceConfig {

	@Bean(name = "selectDataSource")
	@ConfigurationProperties(prefix = "spring.datasource.select")
	public DataSource dataSource1() {
		return DataSourceBuilder.create().build();
	}

	@Bean(name = "updateDataSource")
	@ConfigurationProperties(prefix = "spring.datasource.update")
	public DataSource dataSource2() {
		return DataSourceBuilder.create().build();
	}

}

  

儲存本地資料來源:

DataSourceContextHolder.java

/**
 * 儲存本地多資料來源
 */
@Component
@Lazy(false)
public class DataSourceContextHolder {
	private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

	// 設定資料來源型別
	public static void setDbType(String dbType) {
		contextHolder.set(dbType);
	}

	public static String getDbType() {
		return contextHolder.get();
	}

	public static void clearDbType() {
		contextHolder.remove();
	}

}

 

配置動態切換資料來源類:

DynamicDataSource.java

/**
 * 該類繼承自 AbstractRoutingDataSource 類,在訪問資料庫時會呼叫該類的 determineCurrentLookupKey() 方法獲取資料庫例項的 key
 */
@Component
@Primary
public class DynamicDataSource extends AbstractRoutingDataSource {
	private static final Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);
	@Autowired
	@Qualifier("selectDataSource")
	private DataSource selectDataSource;
	@Autowired
	@Qualifier("updateDataSource")
	private DataSource updateDataSource;

	/**
	 * 返回生效的資料來源名稱
	 */
	@Override
	protected Object determineCurrentLookupKey() {
		logger.info("DataSourceContextHolder:{}", DataSourceContextHolder.getDbType());
		return DataSourceContextHolder.getDbType();
	}
	/**
	 * 配置使用的資料來源資訊,如果不存在就使用預設的資料來源
	 */
	@Override
	public void afterPropertiesSet() {
		Map<Object, Object> map = new HashMap<>();
		map.put("selectDataSource", selectDataSource);
		map.put("updateDataSource", updateDataSource);
		//註冊資料來源
		setTargetDataSources(map);
		setDefaultTargetDataSource(updateDataSource);
		super.afterPropertiesSet();
	}
}

  

AOP配置:

DataSourceAOP.java

@Aspect
@Component
@Lazy(false)
// Order設定AOP執行順序 使之在資料庫事務上先執行
@Order(0)
public class DataSourceAOP {
    private static final Logger logger = LoggerFactory.getLogger(DataSourceAOP.class);
    //橫切點
    @Before("execution(* com.yk.service.*.*(..))")
    public void process(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        if (methodName.startsWith("get") || methodName.startsWith("count") || methodName.startsWith("find")
                || methodName.startsWith("list") || methodName.startsWith("select") || methodName.startsWith("check")) {
            DataSourceContextHolder.setDbType("selectDataSource");
            logger.info("使用的是讀資料來源:selectDataSource");
        } else {
            DataSourceContextHolder.setDbType("updateDataSource");
            logger.info("使用的是寫資料來源:updateDataSource");
        }
    }
}

  

 

application.ymlspring: datasource:####寫資料來源 update: jdbc-url:jdbc:mysql://192.168.100.150:8066/test driver-class-name:com.mysql.jdbc.Driver username:root password:root###讀資料來源 select: jdbc-url:jdbc:mysql://192.168.100.150:8066/test driver-class-name:com.mysql.jdbc.Driver username:user password:user type:com.alibaba.druid.pool.DruidDataSource