SpringBoot整合多数据源(aop,自定义注解实现)

https://blog.csdn.net/y_index/article/details/97806367
1、数据库配置

  1. server:
  2. port: 10000
  3. spring:
  4. datasource:
  5. initialize: false
  6. name: MySQL
  7. druid:
  8. first:
  9. url: jdbc:mysql://192.168.199.86:3306/aoshop?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
  10. username: ddb_dev
  11. password: 123456
  12. second:
  13. url: jdbc:mysql://192.168.199.45:3306/aoshop?useUnicode=true&characterEncoding=utf8&characterSetResults=utf8
  14. username: test_all
  15. password: 123456
  16. type: com.alibaba.druid.pool.DruidDataSource
  17. driver-class-name: com.mysql.jdbc.Driver
  18. initialSize: 5
  19. maxActive: 1000
  20. minIdle: 5
  21. maxWait: 10000
  22. timeBetweenEvictionRunsMillis: 60000
  23. minEvictableIdleTimeMillis: 30000
  24. validationQuery: SELECT 1 FROM DUAL
  25. testWhileIdle: true
  26. testOnBorrow: false
  27. testOnReturn: false
  28. poolPreparedStatements: true
  29. maxPoolPreparedStatementPerConnectionSize: 20
  30. filters: stat,wall,log4j
  31. connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
  32. logSlowSql: true
  33. swagger:
  34. host: 127.0.0.1:9000
  35. enable: true
  36. logging:
  37. config: classpath:logs.xml
  38. level:
  39. com.jinglitong.shop.mapper: debug

2、注解类

  1. @Target({ ElementType.METHOD})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface DataSource {
  5. String name() default "";

3、配置数据源

  1. public interface DataSourceNames {
  2. String FIRST = "first";
  3. String SECOND = "second";
  4. }

4、动态数据源加载

  1. public class DynamicDataSource extends AbstractRoutingDataSource {
  2. //用来保存数据源与获取数据源
  3. private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
  4. public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
  5. super.setDefaultTargetDataSource(defaultTargetDataSource);
  6. super.setTargetDataSources(targetDataSources);
  7. super.afterPropertiesSet();
  8. }
  9. @Override
  10. protected Object determineCurrentLookupKey() {
  11. return getDataSource();
  12. }
  13. public static void setDataSource(String dataSource) {
  14. contextHolder.set(dataSource);
  15. }
  16. public static String getDataSource() {
  17. return contextHolder.get();
  18. }
  19. public static void clearDataSource() {
  20. contextHolder.remove();
  21. }
  22. }

5、把信息加载到配置中

  1. @Configuration
  2. @MapperScan("com.jinglitong.shop.mapper")
  3. public class DynamicDataSourceConfig {
  4. @Bean
  5. @ConfigurationProperties("spring.datasource.druid.first")
  6. public DataSource firstDataSource(){
  7. return DruidDataSourceBuilder.create().build();
  8. }
  9. @Bean
  10. @ConfigurationProperties("spring.datasource.druid.second")
  11. public DataSource secondDataSource(){
  12. return DruidDataSourceBuilder.create().build();
  13. }
  14. @Bean
  15. @Primary
  16. public DynamicDataSource dataSource(DataSource firstDataSource, DataSource secondDataSource) {
  17. Map<Object, Object> targetDataSources = new HashMap<>();
  18. targetDataSources.put(DataSourceNames.FIRST, firstDataSource);
  19. targetDataSources.put(DataSourceNames.SECOND, secondDataSource);
  20. return new DynamicDataSource(firstDataSource, targetDataSources);
  21. }
  22. }

6、aop代理一下

  1. @Aspect
  2. @Component
  3. public class DataSourceAspect implements Ordered{
  4. protected Logger logger = LoggerFactory.getLogger(getClass());
  5. @Pointcut("@annotation(com.jinglitong.shop.datasource.DataSource)")//这个注解DataSource的包名
  6. public void dataSourcePointCut() {
  7. }
  8. @Around("dataSourcePointCut()")
  9. public Object around(ProceedingJoinPoint point) throws Throwable {
  10. MethodSignature signature = (MethodSignature) point.getSignature();
  11. Method method = signature.getMethod();
  12. DataSource ds = method.getAnnotation(DataSource.class);
  13. if(ds == null){
  14. DynamicDataSource.setDataSource(DataSourceNames.FIRST);
  15. System.out.println("FIRST");
  16. logger.debug("set datasource is " + DataSourceNames.FIRST);
  17. }else {
  18. System.out.println(ds.name());
  19. DynamicDataSource.setDataSource(ds.name());
  20. logger.debug("set datasource is " + ds.name());
  21. }
  22. try {
  23. return point.proceed();
  24. } finally {
  25. DynamicDataSource.clearDataSource();
  26. logger.debug("clean datasource");
  27. }
  28. }
  29. @Override
  30. public int getOrder() {
  31. return 1;
  32. }
  33. }

7、在service层使用自定义注解
20190730190128253.png
8、启动类
2019073019024732.png