1.加入依賴
<!-- springboot-aop包,AOP切面注解,Aspectd等相關(guān)注解 -->
????????<dependency>
????????????<groupId>org.springframework.boot</groupId>
????????????<artifactId>spring-boot-starter-aop</artifactId>
????????</dependency>
2.新建一個(gè)注解伦泥,便于切換數(shù)據(jù)源
/**
* @program: springboot_course
* @description: 多數(shù)據(jù)源注解
* @author: ChenZhiXiang
* @create: 2019-06-12 09:21
**/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {
????String value() default "primaryDataSource";
}
3.新建一個(gè)類DataSourceContextHolder洋只,用于保存本地?cái)?shù)據(jù)源
/**
* @program: springboot_course
* @description: 用于保存本地?cái)?shù)據(jù)源
* @author: ChenZhiXiang
* @create: 2019-06-12 09:24
**/
public class DataSourceContextHolder {
????/**
?????* 默認(rèn)數(shù)據(jù)源
?????*/
????public static final String DEFAULT_DS = "primaryDataSource";
????/**
?????* ThreadLocal之后會進(jìn)行講解
?????*/
????private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
????/** 設(shè)置數(shù)據(jù)源名 */
????public static void setDB(String dbType) {
????????System.out.println("切換到{"+dbType+"}數(shù)據(jù)源");
????????contextHolder.set(dbType);
????}
????/** 獲取數(shù)據(jù)源名 */
????public static String getDB() {
????????return (contextHolder.get());
????}
????/** 清除數(shù)據(jù)源名 */
????public static void clearDB() {
????????contextHolder.remove();
????}
}
4.新建DynamicDataSource類用于獲取本地?cái)?shù)據(jù)源
/**
* @program: springboot_course
* @description: 獲取本地?cái)?shù)據(jù)源
* @author: ChenZhiXiang
* @create: 2019-06-12 09:26
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
????@Override
????protected Object determineCurrentLookupKey() {
????????System.out.println("數(shù)據(jù)源為"+DataSourceContextHolder.getDB());
????????return DataSourceContextHolder.getDB();
????}
}
5.新建DataSourceConfig讀取配置
/**
* @program: springboot_course
* @description: 多數(shù)據(jù)源配置類
* @author: ChenZhiXiang
* @create: 2019-06-12 09:27
**/
@Configuration
public class DataSourceConfig {
????@Autowired
????private Environment env;
????/**
?????* 數(shù)據(jù)源1
?????*??prefix application.properteis中對應(yīng)屬性的前綴
?????* @return
?????*/
????@Bean(name = "primaryDataSource")
????@ConfigurationProperties(prefix = "spring.datasource.primary")
????public DataSource primaryDataSource() {
????????return DataSourceBuilder.create().build();
????}
????/**
?????* 數(shù)據(jù)源2
?????* @return
?????*/
????@Bean(name = "secondDataSource")
????@ConfigurationProperties(prefix = "spring.datasource.second")
????public DataSource secondDataSource() {
????????return DataSourceBuilder.create().build();
????}
????/**
?????* 動態(tài)數(shù)據(jù)源: 通過AOP在不同數(shù)據(jù)源之間動態(tài)切換
?????* @return
?????*/
????@Primary
????@Bean(name = "dynamicDataSource")
????public DynamicDataSource dynamicDataSource() {
????????DynamicDataSource dynamicDataSource = new DynamicDataSource();
????????// 默認(rèn)數(shù)據(jù)源
????????dynamicDataSource.setDefaultTargetDataSource(primaryDataSource());
????????// 配置多數(shù)據(jù)源
????????Map<Object, Object> dsMap = new HashMap();
????????dsMap.put("primaryDataSource", primaryDataSource());
????????dsMap.put("secondDataSource", secondDataSource());
????????dynamicDataSource.setTargetDataSources(dsMap);
????????return dynamicDataSource;
????}
????/**
?????* 根據(jù)數(shù)據(jù)源創(chuàng)建SqlSessionFactory
?????*/
????@Bean
????public SqlSessionFactory sqlSessionFactory(DynamicDataSource ds) throws Exception {
????????SqlSessionFactoryBean fb = new SqlSessionFactoryBean();
????????// 指定數(shù)據(jù)源(這個(gè)必須有瘾敢,否則報(bào)錯(cuò))
????????fb.setDataSource(ds);
????????// 下邊兩句僅僅用于*.xml文件稽鞭,如果整個(gè)持久層操作不需要使用到xml文件的話(只用注解就可以搞定),則不加, 指定基包
????????fb.setTypeAliasesPackage(env.getProperty("mybatis.type-aliases-package"));
????????fb.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapper-locations")));
????????return fb.getObject();
????}
????/**
?????* 配置@Transactional注解事物
?????* @return
?????*/
????@Bean
????public PlatformTransactionManager transactionManager() {
????????return new DataSourceTransactionManager(dynamicDataSource());
????}
}
6.新建DynamicDataSourceAspect.java類用于自定義注解 + AOP的方式實(shí)現(xiàn)數(shù)據(jù)源動態(tài)切換址貌。
/**
* @program: springboot_course
* @description: java類用于自定義注解 + AOP的方式實(shí)現(xiàn)數(shù)據(jù)源動態(tài)切換
* @author: ChenZhiXiang
* @create: 2019-06-12 09:31
**/
@Aspect
@Component
public class DynamicDataSourceAspect {
????@Pointcut(value = "execution(* com.example.service.*.*(..))")
????public void pointcut() {
????}
????@Before("pointcut()")
????public void beforeSwitchDS(JoinPoint point){
????????//獲得當(dāng)前訪問的class
????????Class<?> className = point.getTarget().getClass();
????????//獲得訪問的方法名
????????String methodName = point.getSignature().getName();
????????//得到方法的參數(shù)的類型
????????Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
????????String dataSource = DataSourceContextHolder.DEFAULT_DS;
????????try {
????????????// 得到訪問的方法對象
????????????Method method = className.getMethod(methodName, argClass);
????????????// 判斷是否存在@DS注解
????????????if (method.isAnnotationPresent(DataSource.class)) {
????????????????DataSource annotation = method.getAnnotation(DataSource.class);
????????????????// 取出注解中的數(shù)據(jù)源名
????????????????dataSource = annotation.value();
????????????}
????????} catch (Exception e) {
????????????e.printStackTrace();
????????}
????????// 切換數(shù)據(jù)源
????????DataSourceContextHolder.setDB(dataSource);
????}
????@After("pointcut()")
????public void afterSwitchDS(JoinPoint point){
????????DataSourceContextHolder.clearDB();
????}
}
7.添加配置文件
yml方式
spring:
??datasource:
? ? primaryDataSource:
??????jdbc-url: jdbc:mysql:/localhost:3306/test1?useUnicode=true&characterEncoding=UTF-8&useSSL=false&failOverReadOnly=false
??????username: test1
??????password: 123456
??????type: com.alibaba.druid.pool.DruidDataSource
??????driver-class-name: com.mysql.jdbc.Driver
? ?secondDataSource:
??????jdbc-url: jdbc:mysql://localhost:3306/test2?useUnicode=true&characterEncoding=UTF-8&useSSL=false&failOverReadOnly=false
??????username: test2
??????password: 123456
??????type: com.alibaba.druid.pool.DruidDataSource
??????driver-class-name: com.mysql.jdbc.Driver
properties方式
spring.datasource.primary.jdbc-url=jdbc:mysql://192.168.0.194:3306/channel-reward?characterEncoding=UTF-8&useSSL=true&serverTimezone=GMT%2B8&useUnicode=true
spring.datasource.primary.username=root
spring.datasource.primary.password=bonc_mysql
spring.datasource.primary.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.second.jdbc-url=jdbc:mysql://localhost:3306/czx?characterEncoding=UTF-8&useSSL=true&serverTimezone=GMT%2B8&useUnicode=true
spring.datasource.second.username=
spring.datasource.second.password=
spring.datasource.second.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.second.driver-class-name=com.mysql.cj.jdbc.Driver
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.example.pojo
8.使用荔燎,使用注解自主切換