本人做的是后台管理项目,基于配置文件application.yml,我这里配置的是两个数据源,一读一写,没有使用ali的Druid,这个喜欢可以自己加在配置在文件里
datasource:
name: master
url: jdbc:mysql://127.0.0.1:3306/test52?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
username:
password:
driver-class-name: com.mysql.jdbc.Driver
hikari:
max-lifetime: 1765000 #一个连接的生命时长(毫秒),超时而且没被使用则被释放(retired),缺省:30分钟,建议设置比数据库超时时长少30秒以上
maximum-pool-size: 15 #连接池中允许的最大连接数。缺省值:10;推荐的公式:((core_count * 2) + effective_spindle_count)
readdb:
name: readdb
url: jdbc:mysql://127.0.0.1:3306/swingcard?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
password:
driver-class-name: com.mysql.jdbc.Driver
接下来根据配置文件配置数据源:
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
private final Logger logger = LoggerFactory.getLogger(DataSourceConfig.class);
@Bean(name="masterDataSource",destroyMethod = "close" )
@ConfigurationProperties(prefix="spring.datasource")
public DataSource masterDataSource() {
logger.info("主库初始化");
return new org.apache.tomcat.jdbc.pool.DataSource();
}
@Bean(name="slaveDataSource")
@ConfigurationProperties(prefix = "spring.readdb")
public DataSource slaveDataSource() {
return new org.apache.tomcat.jdbc.pool.DataSource();
}
@Bean(name="dynamicDataSource")
@Primary
public DynamicDataSource getDataSource() {
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSources());
return dataSource;
}
private Map
枚举的数据连接类型:主从配置和数据源的动态切换
public enum DataSourceType {
MASTER("master"),
SLAVE("slave");
private String type;
DataSourceType(String type) {
this.type = type;
}
public String getType() {
return type;
}
}
public class DataSourceHolder {
private static final ThreadLocal holder = new ThreadLocal<>();
public static void putDataSource(DataSourceType dataSourceType) {
holder.set(dataSourceType.getType());
}
public static String getDataSource() {
return holder.get();
}
public static void clearDataSourceType() {
holder.remove();
}
}
数据库路由:这里fianally中的方法根据自己需求来决定是否使用,我这里是因为想要的实现结果是默认都是主库的,个别方法才会读取从库数据,这里是清除从库的记录,(注:没有这个方法时出现过在没有加从库注解的方法去使用了从库的数据源,这只是我个人的问题,仅供参考)
public class DynamicDataSource extends AbstractRoutingDataSource{
@Override
protected Object determineCurrentLookupKey() {
if(null!=DataSourceHolder.getDataSource()) {
try {
return DataSourceHolder.getDataSource();
}finally {
DataSourceHolder.clearDataSourceType();
}
}
return DataSourceType.MASTER.getType();
}
}
默认数据源:这里的RetentionPolicy和ElementType可能要手动导入
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
@Inherited
public @interface DataSource {
DataSourceType value() default DataSourceType.MASTER;
}
切面值入:
@Configuration
@Aspect
public class DataSourceAspect implements Ordered{
//使用@DataSource注解的时候会设置具体使用的数据源
@Before(value = "@annotation(dataSource)")
public void dataSourcePoint(JoinPoint jp, DataSource dataSource) {
DataSourceHolder.putDataSource(dataSource.value());
}
//order 越低,代表优先级越高
@Override
public int getOrder() {
return -1;
}
}
最后在要读取从库数据的serviceImpl实现类的方法上加上注解,即可,(注:事务应该是可以的,因为这里没有用到,需要的话可以打开注解,这个功能还没有测试)
@DataSource(DataSourceType.SLAVE)
// @Transactional(rollbackFor = Exception.class)
public PageInfo selectuserListByCondition(DataGrid grid, String username, String name, String startTime,
String stopTime, String sourceType, String verifiedStatus, String registday) {
grid.getOrderBy();
return PageHelper.startPage(grid.getPageNum(), grid.getPageSize())
.doSelectPageInfo(() -> this.userMapper.selectuserListByCondition());
}
pom文件的就不写了,这些应该是把用到的都写在上面了,如果有什么问题错误或者还缺少什么欢迎指正,新手第一次发博客,把今天解决的问题记录下来,如有不当之处请见谅