test:(修证)

dev
zhang xu 2024-06-08 12:02:28 +08:00
parent ca1760e726
commit aa37b31d18
10 changed files with 252 additions and 468 deletions

View File

@ -1,26 +0,0 @@
package com.muyu;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration;
import com.muyu.common.security.annotation.EnableCustomConfig;
import com.muyu.common.security.annotation.EnableMyFeignClients;
import com.muyu.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
/**
* @ClassDescription:
* @JdkVersion: 17
* @Author: zhangxu
* @Created: 2024/6/3 21:00
*/
@EnableCustomConfig
@EnableCustomSwagger2
@EnableMyFeignClients
@SpringBootApplication(exclude = {DynamicDataSourceAutoConfiguration.class
,DataSourceAutoConfiguration.class})
public class CloudManyDataSourceApplication {
public static void main(String[] args) {
SpringApplication.run(CloudManyDataSourceApplication.class);
}
}

View File

@ -1,52 +0,0 @@
package com.muyu.config;
import com.alibaba.druid.pool.DruidDataSource;
import com.muyu.config.holder.DynamicDataSourceHolder;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import java.util.Map;
/**
* @ClassDescription:
* @JdkVersion: 17
* @Author: zhangxu
* @Created: 2024/6/4 8:54
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class DynamicDataSource extends AbstractRoutingDataSource {
/***
*
*
*
* **/
private Map<Object, Object> defineTargetDataSources;
public void put(String key, DruidDataSource value){
defineTargetDataSources.put(key,value);
}
/**
*
* 线使
* **/
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDynamicDatasourceKey();
}
}

View File

@ -1,34 +0,0 @@
package com.muyu.config.contents;
import com.muyu.common.security.utils.SecurityUtils;
import com.muyu.common.system.remote.RemoteUserService;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
/**
* @ClassDescription:
* @JdkVersion: 17
* @Author: zhangxu
* @Created: 2024/6/6 21:13
*/
public class DataSourceAsp {
@Pointcut("execution(public * com.zhiLian.vehicle.controller.*Controller.*(..))")
public void pointcut() {
}
@Lazy
@Autowired
private RemoteUserService remoteUserService;
@Before("pointcut()")
public void beforeMethod(){
Long userid = SecurityUtils.getLoginUser().getUserid();
remoteUserService.
}
}

View File

@ -1,18 +0,0 @@
package com.muyu.config.contents;
/**
* @ClassDescription:
* @JdkVersion: 17
* @Author: zhangxu
* @Created: 2024/6/4 9:33
*/
public class DatasourceContent {
public final static String PASSWORDS = "sal75-z";
public final static String DATASOURCE_URL = "jdbc:mysql://{}:{}/etl?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai";
public final static String DATASOURCE_USERNAME = "root";
}

View File

@ -1,47 +0,0 @@
package com.muyu.config.domain.model;
import com.muyu.common.core.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import static com.muyu.config.contents.DatasourceContent.*;
/**
* @ClassDescription:
* @JdkVersion: 17
* @Author: zhangxu
* @Created: 2024/6/4 9:30
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class DataSourceInfo {
private String key;
private String url;
private String userName;
private String password;
public static DataSourceInfo getDataSourceInfo(String key,String host,Integer port)
{
return DataSourceInfo.builder()
.key(key)
.url(StringUtils.format(DATASOURCE_URL,host,port))
.userName(DATASOURCE_USERNAME)
.password(PASSWORDS)
.build();
}
}

View File

@ -1,39 +0,0 @@
package com.muyu.config.factory;
import com.alibaba.druid.pool.DruidDataSource;
import com.muyu.config.domain.model.DataSourceInfo;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import java.sql.SQLException;
/**
* @ClassDescription:
* @JdkVersion: 17
* @Author: zhangxu
* @Created: 2024/6/4 9:09
*/
@Log4j2
@Component
public class DruidDataSourceFactory {
public DruidDataSource create(DataSourceInfo dataSourceInfo){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl(dataSourceInfo.getUrl());
druidDataSource.setUsername(dataSourceInfo.getUserName());
druidDataSource.setPassword(dataSourceInfo.getPassword());
druidDataSource.setBreakAfterAcquireFailure(true);
druidDataSource.setConnectionErrorRetryAttempts(0);
try {
druidDataSource.getConnection(2000);
log.info("连接成功");
return druidDataSource;
} catch (SQLException e) {
log.error("连接失败");
return null;
}
}
}

View File

@ -1,36 +1,36 @@
package com.muyu.networking.controller; //package com.muyu.networking.controller;
//
//
import com.muyu.common.core.domain.Result; //import com.muyu.common.core.domain.Result;
import com.muyu.domain.datasources.SongInfo; //import com.muyu.domain.datasources.SongInfo;
import com.muyu.networking.service.SongService; //import com.muyu.networking.service.SongService;
import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; //import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; //import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; //import org.springframework.web.bind.annotation.RestController;
//
import java.util.List; //import java.util.List;
//
/** ///** 多数据源
* songController // * songController
* // *
* @author GuanTieLin // * @author 张zhangxu
* @date 2024-05-16 // * @date 2024-05-16
*/ // */
@RestController //@RestController
@RequestMapping("/song") //@RequestMapping("/song")
public class SongController { //public class SongController {
//
@Autowired // @Autowired
private SongService songService; // songService接口 // private SongService songService; // songService接口
//
/** // /**
* // * 查询歌曲列表
*/ // */
@GetMapping("/list") // @GetMapping("/list")
public Result<List<SongInfo>> list() { // song_info对象 // public Result<List<SongInfo>> list() { // song_info对象
return Result.success(songService.list()); // 查询song列表 // return Result.success(songService.list()); // 查询song列表
} // }
//
} //}
//

View File

@ -1,113 +1,113 @@
package com.muyu.vehicle.config; //package com.muyu.vehicle.config;
import com.alibaba.druid.pool.DruidDataSource; //import com.alibaba.druid.pool.DruidDataSource;
//
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; //import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import lombok.extern.log4j.Log4j2; //import lombok.extern.log4j.Log4j2;
import org.apache.ibatis.session.SqlSessionFactory; //import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Qualifier; //import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value; //import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; //import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; //import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; //import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager; //import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource; //import javax.sql.DataSource;
import java.util.HashMap; //import java.util.HashMap;
import java.util.Map; //import java.util.Map;
//
/** ///**
* Druid // * Druid数据库连接池配置
* @ClassName DruidDBConfig // * @ClassName DruidDBConfig
* @Author // * @Author
* @Date 2024/4/28 17:16 // * @Date 2024/4/28 17:16
*/ // */
@Log4j2 //@Log4j2
@Configuration //@Configuration
public class DruidDBConfig { //public class DruidDBConfig {
//
@Value("${spring.datasource.dynamic.datasource.slave.url}") // @Value("${spring.datasource.dynamic.datasource.slave.url}")
private String dbUrl; // private String dbUrl;
@Value("${spring.datasource.dynamic.datasource.slave.username}") // @Value("${spring.datasource.dynamic.datasource.slave.username}")
private String username; // private String username;
@Value("${spring.datasource.dynamic.datasource.slave.password}") // @Value("${spring.datasource.dynamic.datasource.slave.password}")
private String password; // private String password;
@Value("${spring.datasource.dynamic.datasource.slave.driver-class-name}") // @Value("${spring.datasource.dynamic.datasource.slave.driver-class-name}")
private String driverClassName; // private String driverClassName;
//连接池连接信息 // //连接池连接信息
@Value("${spring.datasource.dynamic.druid.initial-size}") // @Value("${spring.datasource.dynamic.druid.initial-size}")
private int initialSize; // private int initialSize;
@Value("${spring.datasource.dynamic.druid.min-idle}") // @Value("${spring.datasource.dynamic.druid.min-idle}")
private int minIdle; // private int minIdle;
@Value("${spring.datasource.dynamic.druid.max-active}") // @Value("${spring.datasource.dynamic.druid.max-active}")
private int maxActive; // private int maxActive;
@Value("${spring.datasource.dynamic.druid.max-wait}") // @Value("${spring.datasource.dynamic.druid.max-wait}")
private int maxWait; // private int maxWait;
//
@Bean // @Bean
@Primary // @Primary
@Qualifier("mainDataSource") // @Qualifier("mainDataSource")
public DataSource dataSource() { // public DataSource dataSource() {
DruidDataSource datasource = new DruidDataSource(); // DruidDataSource datasource = new DruidDataSource();
// 基础连接信息 // // 基础连接信息
datasource.setUrl(this.dbUrl); // datasource.setUrl(this.dbUrl);
datasource.setUsername(username); // datasource.setUsername(username);
datasource.setPassword(password); // datasource.setPassword(password);
datasource.setDriverClassName(driverClassName); // datasource.setDriverClassName(driverClassName);
// 连接池连接信息 // // 连接池连接信息
datasource.setInitialSize(initialSize); // datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle); // datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive); // datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait); // datasource.setMaxWait(maxWait);
//是否缓存preparedStatement也就是PSCache。PSCache对支持游标的数据库性能提升巨大比如说oracle。在mysql下建议关闭。 // //是否缓存preparedStatement也就是PSCache。PSCache对支持游标的数据库性能提升巨大比如说oracle。在mysql下建议关闭。
datasource.setPoolPreparedStatements(false); // datasource.setPoolPreparedStatements(false);
datasource.setMaxPoolPreparedStatementPerConnectionSize(20); // datasource.setMaxPoolPreparedStatementPerConnectionSize(20);
//申请连接时执行validationQuery检测连接是否有效这里建议配置为TRUE防止取到的连接不可用 // //申请连接时执行validationQuery检测连接是否有效这里建议配置为TRUE防止取到的连接不可用
datasource.setTestOnBorrow(true); // datasource.setTestOnBorrow(true);
//建议配置为true不影响性能并且保证安全性。申请连接的时候检测如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效。 // //建议配置为true不影响性能并且保证安全性。申请连接的时候检测如果空闲时间大于timeBetweenEvictionRunsMillis执行validationQuery检测连接是否有效。
datasource.setTestWhileIdle(true); // datasource.setTestWhileIdle(true);
//用来检测连接是否有效的sql // //用来检测连接是否有效的sql
datasource.setValidationQuery("select 1 from dual"); // datasource.setValidationQuery("select 1 from dual");
//配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 // //配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
datasource.setTimeBetweenEvictionRunsMillis(60000); // datasource.setTimeBetweenEvictionRunsMillis(60000);
//配置一个连接在池中最小生存的时间单位是毫秒这里配置为3分钟180000 // //配置一个连接在池中最小生存的时间单位是毫秒这里配置为3分钟180000
datasource.setMinEvictableIdleTimeMillis(180000); // datasource.setMinEvictableIdleTimeMillis(180000);
datasource.setKeepAlive(true); // datasource.setKeepAlive(true);
return datasource; // return datasource;
} // }
//
//
@Bean(name = "dynamicDataSource") // @Bean(name = "dynamicDataSource")
@Qualifier("dynamicDataSource") // @Qualifier("dynamicDataSource")
public DynamicRoutingDataSource dynamicDataSource() { // public DynamicRoutingDataSource dynamicDataSource() {
DynamicRoutingDataSource dynamicDataSource = new DynamicRoutingDataSource(); // DynamicRoutingDataSource dynamicDataSource = new DynamicRoutingDataSource();
dynamicDataSource.setDebug(false); // dynamicDataSource.setDebug(false);
//配置缺省的数据源 // //配置缺省的数据源
dynamicDataSource.setDefaultTargetDataSource(dataSource()); // dynamicDataSource.setDefaultTargetDataSource(dataSource());
Map<Object, Object> targetDataSources = new HashMap<Object, Object>(); // Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
//额外数据源配置 TargetDataSources // //额外数据源配置 TargetDataSources
targetDataSources.put("mainDataSource", dataSource()); // targetDataSources.put("mainDataSource", dataSource());
dynamicDataSource.setTargetDataSources(targetDataSources); // dynamicDataSource.setTargetDataSources(targetDataSources);
return dynamicDataSource; // return dynamicDataSource;
} // }
//
//
@Bean // @Bean
public SqlSessionFactory sqlSessionFactory() throws Exception { // public SqlSessionFactory sqlSessionFactory() throws Exception {
//用mybatis的这里会有点区别mybatis用的是SqlSessionFactoryBean // //用mybatis的这里会有点区别mybatis用的是SqlSessionFactoryBean
MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean(); // MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dynamicDataSource()); // sqlSessionFactoryBean.setDataSource(dynamicDataSource());
//配置resources包下的xml文件扫描路径 // //配置resources包下的xml文件扫描路径
//sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/*.xml")); // //sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:/mapper/*.xml"));
return sqlSessionFactoryBean.getObject(); // return sqlSessionFactoryBean.getObject();
} // }
//
/** // /**
* // * 将动态数据加载类添加到事务管理器
* @param dataSource // * @param dataSource 数据源
* @return org.springframework.jdbc.datasource.DataSourceTransactionManager // * @return org.springframework.jdbc.datasource.DataSourceTransactionManager
*/ // */
@Bean // @Bean
public DataSourceTransactionManager transactionManager(DynamicRoutingDataSource dataSource) { // public DataSourceTransactionManager transactionManager(DynamicRoutingDataSource dataSource) {
return new DataSourceTransactionManager(dataSource); // return new DataSourceTransactionManager(dataSource);
} // }
} //}
//

View File

@ -1,44 +1,44 @@
package com.muyu.vehicle.context; //package com.muyu.vehicle.context;
//
import com.alibaba.ttl.TransmittableThreadLocal; //import com.alibaba.ttl.TransmittableThreadLocal;
import lombok.extern.log4j.Log4j2; //import lombok.extern.log4j.Log4j2;
//
/** ///**
* // * 当前数据源
* @ClassName DataSourceContextHolder // * @ClassName DataSourceContextHolder
* @Author // * @Author
* @Date 2024/4/28 16:47 // * @Date 2024/4/28 16:47
*/ // */
@Log4j2 //@Log4j2
public class DataSourceContextHolder { //public class DataSourceContextHolder {
//
/** // /**
* 线 // * 线程级别的私有变量
*/ // */
private static final TransmittableThreadLocal<Long> CONTEXT_HOLDER = new TransmittableThreadLocal<>(); // private static final TransmittableThreadLocal<Long> CONTEXT_HOLDER = new TransmittableThreadLocal<>();
//
/** // /**
* // * 切换数据源
*/ // */
public static void setDataSource(Long datasourceId) { // public static void setDataSource(Long datasourceId) {
CONTEXT_HOLDER.set(datasourceId); // CONTEXT_HOLDER.set(datasourceId);
log.info("已切换到数据源:{}",datasourceId); // log.info("已切换到数据源:{}",datasourceId);
} // }
//
/** // /**
* // * 获取当前数据源
* @return // * @return 数据源编号
*/ // */
public static Long getDataSource() { // public static Long getDataSource() {
return CONTEXT_HOLDER.get(); // return CONTEXT_HOLDER.get();
} // }
//
/** // /**
* // * 删除数据源
*/ // */
public static void removeDataSource() { // public static void removeDataSource() {
CONTEXT_HOLDER.remove(); // CONTEXT_HOLDER.remove();
log.info("已切换到主数据源"); // log.info("已切换到主数据源");
} // }
} //}
//

View File

@ -1,59 +1,59 @@
package com.muyu.vehicle.service.Impl; //package com.muyu.vehicle.service.Impl;
//
//
//
import com.muyu.domain.datasources.Datasource; //import com.muyu.domain.datasources.Datasource;
//
import com.muyu.vehicle.config.DynamicRoutingDataSource; //import com.muyu.vehicle.config.DynamicRoutingDataSource;
import com.muyu.vehicle.context.DataSourceContextHolder; //import com.muyu.vehicle.context.DataSourceContextHolder;
import com.muyu.vehicle.mapper.DataSourceMapper; //import com.muyu.vehicle.mapper.DataSourceMapper;
import com.muyu.vehicle.service.DataSourceService; //import com.muyu.vehicle.service.DataSourceService;
import org.springframework.beans.factory.annotation.Autowired; //import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; //import org.springframework.stereotype.Service;
//
import java.util.List; //import java.util.List;
//
/** ///**
* @ClassName // * @ClassName
* @Author // * @Author
* @Date // * @Date
*/ // */
@Service //@Service
public class DataSourceServiceImpl implements DataSourceService { //public class DataSourceServiceImpl implements DataSourceService {
//
@Autowired // @Autowired
private DataSourceMapper dataSourceMapper; // private DataSourceMapper dataSourceMapper;
//
@Autowired // @Autowired
private DynamicRoutingDataSource dynamicRoutingDataSource; // private DynamicRoutingDataSource dynamicRoutingDataSource;
//
@Override // @Override
public void toDefaultDS() { // public void toDefaultDS() {
//切到默认数据源 // //切到默认数据源
DataSourceContextHolder.removeDataSource(); // 删除数据源 // DataSourceContextHolder.removeDataSource(); // 删除数据源
} // }
//
@Override // @Override
public boolean changeDS(Long datasourceId) { // public boolean changeDS(Long datasourceId) {
//切到默认数据源 // //切到默认数据源
DataSourceContextHolder.removeDataSource(); // 删除数据源 // DataSourceContextHolder.removeDataSource(); // 删除数据源
//找到所有的配置 // //找到所有的配置
List<Datasource> dataSourceList = dataSourceMapper.selectList(null); // 数据源对象 // List<Datasource> dataSourceList = dataSourceMapper.selectList(null); // 数据源对象
//
if(!dataSourceList.isEmpty()){ // if(!dataSourceList.isEmpty()){
for (Datasource dataSource : dataSourceList) { // 数据源对象 // for (Datasource dataSource : dataSourceList) { // 数据源对象
if(dataSource.getId().equals(datasourceId)){ // 编号 // if(dataSource.getId().equals(datasourceId)){ // 编号
System.out.println("已找到数据源,datasourceId是" + dataSource.getId()); // 编号 // System.out.println("已找到数据源,datasourceId是" + dataSource.getId()); // 编号
//判断连接是否存在,不存在就创建 // //判断连接是否存在,不存在就创建
dynamicRoutingDataSource.checkCreateDataSource(dataSource); // 检查数据源是否已经创建 // dynamicRoutingDataSource.checkCreateDataSource(dataSource); // 检查数据源是否已经创建
//切换数据源 // //切换数据源
DataSourceContextHolder.setDataSource(dataSource.getId()); // 编号 --> 切换数据源 // DataSourceContextHolder.setDataSource(dataSource.getId()); // 编号 --> 切换数据源
return true; // return true;
} // }
} // }
} // }
return false; // return false;
} // }
//
} //}
//