前言:

我们在开发项目时,有时不止访问一个数据库,可能会同时连接多个数据库。如果通过写接口的方式进行访问,如果其中一个项目中断,则会影响系统的运行,如果解决这种问题呢?最好的方式就是直接访问数据库,这样不但效率高,而且可以减少大量的开发任务。

一、数据库配置文件目录,如图:

在这里插入图片描述

二、文件内容详情

1、DataSourceAspect

/**
 * 使用切面进行数据库切换
 * @author charlin
 * @version 0.01
 */
@Aspect
@Component
@Slf4j
public class DataSourceAspect implements Ordered {
 

	@Pointcut("@annotation(com.wys.mall.dataSource.IDataSource)")//注意:这里的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();
		IDataSource ds = method.getAnnotation(IDataSource.class);
		if (ds == null) {
			DynamicDataSource.setDataSource(DataSourceNames.CLOUD);
			log.debug("set datasource is " + DataSourceNames.CLOUD);
		} else {
			DynamicDataSource.setDataSource(ds.name());
			log.debug("set datasource is " + ds.name());
		}
		try {
			return point.proceed();
		} finally {
			DynamicDataSource.clearDataSource();
			log.debug("clean datasource");
		}
	}

	@Override
	public int getOrder() {
		return 1;
	}
}

2、DataSourceNames

/**
 * 数据源名称
 * @author charlin
 * @version 0.01
 * @date 2020-09-20
 */
public interface DataSourceNames {
    String CLOUD = "cloud";
    String YAODIAN = "yaodian";
}

3、DynamicDataSource

/**
 * 设置数据源切换
 * @author chalrin
 * @version 0.01
 */
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();
    }
}

4、数据源配置DynamicDataSourceConfig

/**
 * 数据源配置
 * @author charlin
 * @version 0.01
 */
@Configuration
public class DynamicDataSourceConfig {
 
    @Bean
    @ConfigurationProperties("spring.datasource.druid.cloud")
    public DataSource cloudDataSource(){
        return DruidDataSourceBuilder.create().build();
    }
    @Bean
    @ConfigurationProperties("spring.datasource.druid.yaodian")
    public DataSource yaodianDataSource(){
    	return DruidDataSourceBuilder.create().build();
    }

 
    @Bean
    @Primary
    public DynamicDataSource dataSource(DataSource cloudDataSource, DataSource yaodianDataSource) {
        Map<String, DataSource> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceNames.CLOUD, cloudDataSource);
        targetDataSources.put(DataSourceNames.YAODIAN, yaodianDataSource);
        return new DynamicDataSource(cloudDataSource, targetDataSources);
    }
    
}

5、设置默认的数据源IDataSource

/**
 * 设置默认的数据源
 * @author charlin
 * @version 0.01
 */
@Target(ElementType.METHOD)
//注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在;
@Retention(RetentionPolicy.RUNTIME)
public @interface IDataSource {
	String name() default "cloud";
}

6、事务控制器TransactionConfig

/**
 * 事务控制器
 * @author charlin
 * @Title: ${file_name}
 * @Package ${package_name}
 * @date 2020/9/2920:43
 */
@Configuration
public class TransactionConfig {

    public static final String CLOUD_TX = "cloud_tx";
    public static final String YAODIAN_TX = "yaodian_tx";

    //使用,在方法上添加 @Transactional(value = TransactionConfig.CLOUD_TX, rollbackFor = Exception.class)

    @Bean(name = TransactionConfig.CLOUD_TX)
    public DataSourceTransactionManager cloudTransactionManager(DataSource cloudDataSource){
        return new DataSourceTransactionManager(cloudDataSource);
    }

    @Bean(name = TransactionConfig.YAODIAN_TX)
    public DataSourceTransactionManager yaodianTransactionManager(DataSource yaodianDataSource){
        return new DataSourceTransactionManager(yaodianDataSource);
    }

}

三、MyBatisPlus配置

/**
 * 作用:mybatisPlus配置<br>
 * 说明:(无)
 *
 * @author charlin
 * @Date 2019年04月08日 16:47
 */
@Configuration
@MapperScan("com.wys.mall.*.mapper")
@EnableTransactionManagement
@Aspect
public class MybatisPlusConfig {

    /**
     * 注入sql注入器
     */
    @Bean
    public ISqlInjector sqlInjector() {
        return new LogicSqlInjector();
    }

    @Bean
    @Profile({"dev","prod","test"})
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        /*<!-- SQL 执行性能分析,开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长 -->*/
        performanceInterceptor.setMaxTime(100000);
        /*<!--SQL是否格式化 默认false-->*/
        performanceInterceptor.setFormat(false);
        return performanceInterceptor;
    }

    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        //文件最大
        factory.setMaxFileSize(DataSize.of(202400L, DataUnit.KILOBYTES)); //KB,MB
        /// 设置总上传数据总大小
        factory.setMaxRequestSize(DataSize.of(1024000L, DataUnit.KILOBYTES));
        return factory.createMultipartConfig();
    }


    /**
     * 配置分页插件
     * @return page
     */
    @Bean
    public PaginationInterceptor paginationInterceptor(){
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }

    /**
     * 乐观锁 配置
     * @return
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        return new OptimisticLockerInterceptor();
    }


    /**
     * 新增/编辑时自动填充修改人/添加人/创建时间/修改日期
     * 自动填充功能
     * @return
     */
    @Bean
    public GlobalConfig globalConfig() {
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setMetaObjectHandler(new MyMetaObjectHandler());
        return globalConfig;
    }


}

四、资源文件配置,如图:

在这里插入图片描述
1、application.yml

server:
  port: 8282
  servlet:
    session:
      timeout: 3600000000s
spring:
  # 使用环境
  profiles:
    active: dev
  session:
    timeout: 3600000000s
  #日期配置
  jackson:
    date-format: yyyy/MM/dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: non_null
  main:
    allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册

# mybatis-plus 配置
mybatis-plus:
  check-config-location: false
  type-aliases-package: com.wys.mall.*.entity
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: false
    #日志输出
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      id-type: UUID
      table-underline: true
      #驼峰下划线转换
      column-underline: true
      db-type: mysql
      logic-delete-value: 1 #默认值1
      logic-not-delete-value: 0 #默认值0
    #刷新mapper
    refresh-mapper: true

#日志
logging:
  config: classpath:logback-spring.xml

log:
  file: D:/log
#swagger api记录
swagger:
  show: true

2、application-dev.yml

spring:
  # druid数据源配置
  datasource:
    name: druidDataSource
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      cloud:
        url: jdbc:mysql://192.168.16.100:9090/member?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
        username: sa
        password: sa
      yaodian:
        url: jdbc:mysql://192.168.16.100:9090/yaodian?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
        username: sa
        password: sa
      filters: stat,wall,config
      max-active: 100
      initial-size: 1
      max-wait: 60000
      min-idle: 1
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      validation-query: select 'x'
      test-while-idle: true
      test-on-borrow: false
      test-on-return: false
      pool-prepared-statements: true
      max-open-prepared-statements: 50
      max-pool-prepared-statement-per-connection-size: 20
      web-stat-filter:
        # 添加过滤规则
        url-pattern: /*
        # 忽略过滤格式
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
      stat-view-servlet:
        # 是否可以重置数据
        reset-enable: false
        # 开启druid监控页面
        enabled: true

  # 静态资料访问方式
  mvc:
    static-path-pattern: /static/**

  # thymeleaf 模块配置
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
    mode: LEGACYHTML5
    encoding: utf-8
    # 关闭页面缓存
    cache: false
    servlet:
      content-type: text/html

  # redis配置
  redis:
    # Redis数据库索引
    database: 0
    # Redis服务器地址
    host: localhost
    port: 6379
    password: 
    jedis:
      pool:
        # 连接池最大连接数(使用负值表示没有限制)
        max-active: 8
        # 连接池最大阻塞等待时间(使用负值表示没有限制)
#        max-wait: -1
        # 连接池中的最大空闲连接
        max-idle: 8
        # 连接池中的最小空闲连接
        min-idle: 0
    # 连接超时时间(毫秒)
    timeout: 10000s  
  session:
    store-type: redis


# cloud自定义配置
cloud:
  # 登录验证码是否开启,开发环境配置false方便测试
  login:
    authcode:
      enable: false
  # quartz开关
  quartz:
    enable: true
  # 缓存开关
  cache:
    enable: false

五、项目中使用

@Override
    @IDataSource(name = DataSourceNames.CLOUD)
    @Transactional(value = TransactionConfig.CLOUD_TX, rollbackFor = Exception.class)
    public Integer update() {
    ..............................
    }

六、启动

@Slf4j
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 360000)
@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, DataSourceAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class })
@EnableScheduling
@EnableTransactionManagement(proxyTargetClass = true)
public class MyApplication extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(MyApplication.class);
    }

}
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐