二、tienchin健身系统下的技术点复现--动态数据源

发布时间 2023-06-04 23:02:36作者: 山沉

二、配置动态数据源

前面我们已经准备了基础的类,@DynamicDatasource、DruidProperties、DynamicAspect

现在我们开始对 AbstractRoutingDatasource 所需要的数据源,放到对应的map结构中。

1、加载数据源

/**
 * 功能描述 加载自定义的数据源,存入到 Map<String,Datasource> 结构中
 *
 * @author [山沉]
 * @个人博客 [https://choleen95.github.io/]
 * @博客 [https://www.cnblogs.com/Choleen/]
 * @since [2023/6/4 10:00]
 */
@Component
@EnableConfigurationProperties(DruidProperties.class)
public class LoadDataSource {

    @Autowired
    DruidProperties druidProperties;

    public Map<String, DataSource> loadDatasource() {
        Map<String, DataSource> map = new HashMap<>();
        // 获取自定义数据源的属性
        Map<String, Map<String, String>> druidMap = druidProperties.getDruid();
        try {
            // 数据源名称 master、slave
            Set<String> keySet = druidMap.keySet();
            for (String name : keySet) {
                map.put(name, druidProperties.dataSource(
                        ((DruidDataSource) DruidDataSourceFactory.createDataSource(druidMap.get(name)))));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

}

2、设置默认、目标数据源

/**
 * 功能描述 重写AbstractRoutingDataSource 的一个方法
 *
 * @author [山沉]
 * @个人博客 [https://choleen95.github.io/]
 * @博客 [https://www.cnblogs.com/Choleen/]
 * @since [2023/6/3 22:49]
 */
@Component
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {

    public DynamicRoutingDataSource(LoadDataSource loadDatasource) {
        Map<String, DataSource> allDataSource = loadDatasource.loadDatasource();
        // 1.设置所有数据源
        super.setTargetDataSources(new HashMap<>(allDataSource));
        // 2.设置默认的数据源
        super.setDefaultTargetDataSource(allDataSource.get(DataSourceType.DEFAULT_DS_TYPE));
        // 3.设置配置
        super.afterPropertiesSet();
    }

    /**
     * 该方法是用来返回数据源的名称,当系统需要获取数据源的时候,会自动调用该方法获取数据源的名称
     *
     * @author 山沉
     * @date 2023/6/4 10:12
     * @return {@link Object}
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceContextHolder.getDatasourceType();
    }
}

到了这一步基本就设置完成,总的来说就是依据 AbstracRoutingDataSource 来存储 target 和 default 的数据源,重写 determineCurrentLookupKey 方法。

/**
 * 功能描述 常用配置变量
 *
 * @author [山沉]
 * @个人博客 [https://choleen95.github.io/]
 * @博客 [https://www.cnblogs.com/Choleen/]
 * @since [2023/6/4 10:22]
 */
public interface DataSourceType {
    String DEFAULT_DS_TYPE = "master";
}

3、单元测试

3.0 创建service、mapper、domian

@Service
public class LoginUserService {

    @Autowired
    private LoginUserMapper loginUserMapper;

    public List<LoginUser> getAllLoginUsers() {
        return loginUserMapper.getAllLoginUsers();
    }
}

public class LoginUser {

    private Long id;
    private String name;

    @Override
    public String toString() {
        return "LoginUser{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

@Mapper
public interface LoginUserMapper {
    /**
     * 查找所有的登录用户
     *
     * @author 山沉
     * @date 2023/6/4 10:41
     * @return {@link List< LoginUser>}
     */
    @Select("select * from t_login_user")
    List<LoginUser> getAllLoginUsers();
}

然后看下数据库

tesdb2、testdb 两个库中有相同的t_login_user表

slave对应如下

master对应如下

3.1 直接访问

直接访问,不添加注解,是默认数据源

3.2 加注解访问