赞
踩
首先需要引入druid连接池依赖 ,此处选择alibaba连接池
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>druid-spring-boot-starter</artifactId>
- <version>1.2.8</version>
- </dependency>
配置数据源信息 可创建多个
- spring:
- datasource:
- druid:
- #第一个数据库连接信息 local
- local:
- type: com.alibaba.druid.pool.DruidDataSource
- username: root
- password: mima
- driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/local?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
- #第二个数据库连接信息 cloud
- cloud:
- type: com.alibaba.druid.pool.DruidDataSource
- username: root
- password: mima
- driver-class-name: com.mysql.cj.jdbc.Driver
- url: jdbc:mysql://localhost:3306/cloud?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true

创建配类DataSourceConfig 注入配置信息
- import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- import javax.sql.DataSource;
-
-
- @Slf4j
- @Configuration
- public class DataSourceConfig {
-
- /**
- * 将cloud数据连接信息注入cloudDataSource
- */
- @Bean(name = "cloudDataSource")
- @ConfigurationProperties(prefix = "spring.datasource.druid.cloud")
- public DataSource cloudDataSource(){
- return DruidDataSourceBuilder.create().build();
- }
-
- /**
- * 将local数据连接信息注入localDataSource
- */
- @Bean(name = "localDataSource")
- @ConfigurationProperties(prefix = "spring.datasource.druid.local")
- public DataSource localDataSource(){
- return DruidDataSourceBuilder.create().build();
- }
- }

创建DataSourceNames类 给数据源命名 便于使用。
- public interface DataSourceNames {
- String cloudDataSource = "CLOUDDATASOURCE";
- String localDataSource = "LOCALDATASOURCE";
- }
自定义注解DataSource 默认选中数据源 localDataSource
- import java.lang.annotation.*;
-
- @Documented
- @Target({ElementType.METHOD})
- @Retention(RetentionPolicy.RUNTIME)
- public @interface DataSource {
- String value() default DataSourceNames.localDataSource;
- }
创建 DynamicDataSource类 extends AbstractRoutingDataSource 重写determineCurrentLookupKey方法
- import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
-
- import javax.sql.DataSource;
- import java.util.Map;
-
- public class DynamicDataSource extends AbstractRoutingDataSource {
- private static final ThreadLocal<String> CONTEXT_HOLDER= new ThreadLocal<>();
-
- /**
- * 配置DataSource, defaultTargetDataSource为主数据库
- */
- public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
- super.setDefaultTargetDataSource(defaultTargetDataSource);
- super.setTargetDataSources(targetDataSources);
- super.afterPropertiesSet();
- }
-
- @Override
- protected Object determineCurrentLookupKey() {
- return getDataSource();
- }
-
- public static void setDataSource(String dataSource) {
- CONTEXT_HOLDER.set(dataSource);
- }
-
- public static String getDataSource() {
- return CONTEXT_HOLDER.get();
- }
-
- public static void clearDataSource() {
- CONTEXT_HOLDER.remove();
- }
- }

创建SqlSessionConfig
- import lombok.extern.slf4j.Slf4j;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.mybatis.spring.SqlSessionFactoryBean;
- import org.springframework.beans.factory.annotation.Qualifier;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.Primary;
- import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
-
- import javax.sql.DataSource;
- import java.util.HashMap;
- import java.util.Map;
-
-
- @Slf4j
- @Configuration
- public class SqlSessionConfig{
- @Bean(name = "dataSource")
- @Primary
- DataSource dataSource(@Qualifier("cloudDataSource") DataSource cloudDataSource , @Qualifier("localDataSource") DataSource localDataSource){
- Map<Object,Object> targetDataSources = new HashMap<>(2);
- targetDataSources.put(DataSourceNames.cloudDataSource,cloudDataSource);
- targetDataSources.put(DataSourceNames.localDataSource,localDataSource);
- log.info("DataSource:{}" + targetDataSources);
- return new DynamicDataSource(localDataSource,targetDataSources);
- }
-
- @Bean
- @Primary
- public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
- SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
- bean.setDataSource(dataSource);
- //在yml文件中配置开启驼峰式命名转化时不生效,在此设置
- bean.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);
- bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:mapper/*.xml"));
- return bean.getObject();
- }
- }

配置切面 在使用自定义@DataSource注解时 将指定数据源注入
- import lombok.extern.slf4j.Slf4j;
- import org.aspectj.lang.ProceedingJoinPoint;
- import org.aspectj.lang.annotation.Around;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Pointcut;
- import org.aspectj.lang.reflect.MethodSignature;
- import org.springframework.stereotype.Component;
-
- import java.lang.reflect.Method;
-
- @Component
- @Aspect
- @Slf4j
- public class DataSourceAspect {
- @Pointcut("@annotation(com.zhuodao.config.DataSource)")
- public void pointCut(){}
-
- @Around("pointCut()")
- public Object around(ProceedingJoinPoint point) throws Throwable {
- MethodSignature signature = (MethodSignature) point.getSignature();
- Method method = signature.getMethod();
- DataSource dataSource = method.getAnnotation(DataSource.class);
- DynamicDataSource.setDataSource(dataSource.value());
- log.info("set dataSource is {}" , dataSource.value());
- try {
- return point.proceed();
- }finally {
- DynamicDataSource.clearDataSource();
- log.info("clearDataSource");
- }
- }
- }

注解注入 在操作数据库时指定数据源 使用@DataSource()注解 示例如下
- @Service
- public class CloudTaskServiceImpl implements CloudTaskService {
-
- @Autowired
- private TaskMapper taskMapper;
-
- //注解注入
- @Override
- @DataSource(value = DataSourceNames.cloudDataSource)
- public int insertTask(Task task) {
- return taskMapper.insert(task);
- }
- }
- @Service
- @Slf4j
- public class LocalTaskServiceImpl implements LocalTaskService {
- @Autowired
- private TaskMapper taskMapper;
-
- @Override
- @DataSource //使用默认数据库
- public List<Task> selectAll() {
- log.info("task"+taskMapper.selectAll().size());
- return taskMapper.selectAll();
- }
- }
在某些业务上,可能要操作多个数据库,那么使用注解在方法上注入数据源就不是那么的方便,所以就需要手动注入
手动注入 在操作数据库前使用DynamicDataSource.setDataSource("")方法 也可注入 示例如下
- @Service
- public class CloudTaskServiceImpl implements CloudTaskService {
-
- @Autowired
- private TaskMapper taskMapper;
-
- //手动注入
- @Override
- public int insertTask(Task task) {
- DynamicDataSource.setDataSource("CLOUDDATASOURCE");
- return taskMapper.insert(task);
- }
- }
可能会遇到的问题
切面方法不执行 需要加入aspectjrt, aspectjweaver依赖 ,缺一不可!
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjrt</artifactId>
- <version>1.9.7</version>
- </dependency>
-
- <dependency>
- <groupId>org.aspectj</groupId>
- <artifactId>aspectjweaver</artifactId>
- <version>1.9.7</version>
- </dependency>
如果你恰好也有可以用多数据源实现的类似场景,希望对你有帮助。如有写的不对或不够好的地方,欢迎指正。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。