赞
踩
context-path: /db
mybatis:
mapper-locations: classpath:mappers/*xml
type-aliases-package: jin.panpan.database.entity
#日志配置
logging:
config: classpath:log4j2.xml
复制代码
配置文件, 除了基本的应用名称、端口、路径、日志等配置以外, 主要看数据库驱动的配置, 这里我们不像平时的单数据源的配置, 我们需要配置多个数据源, 上面示例的配置文件里, 由两个注意点:
db1和db2是我们自定义的数据源名称, 这个我们在后面的MybatisConfig文件里会用到
数据源里的配置jdbc-url
对应单数据源配置里的url
, 这里使用url会注入失败
${db1.username}等是导入的application-jdbc.properties
文件里的配置值
db1.username = user
db1.password =
db1.url = jdbc:mysql://xx.xx.xx.xx:3306/db1
db2.username = user
db2.password =
db2.url = jdbc:mysql://xx.xx.xx.xx:3306/db2
复制代码
key-value结构, key可以在引入此文件的配置里使用${key}引用
这里我们使用两个数据库, 但是数据库的表结构一致(至少多数据源涉及到的表需要结构一致), 以避免不能共用一套代码
public enum DataSourceType {
//NONE用来返回默认
NONE(“”),
DB1(“db1”),
DB2(“db2”),
;
//省略部分代码
}
复制代码
此文件是数据源的枚举, 这里的枚举我们只配置里一个参数, 可以依据业务扩展. 本枚举的值代表数据源的名称, 是和配置文件里的配置对应上的
另外说明一下, NONE是用来代表默认数据源的, 是为了方便编程添加的, 不是必须的
public class DataSourceUtil {
private static final ThreadLocal localDataSource = new ThreadLocal<>();
private DataSourceUtil(){
}
public static DataSourceType get() {
return localDataSource.get();
}
public static void set(DataSourceType type){
localDataSource.set(type);
}
public static void remove() {
localDataSource.remove();
}
}
复制代码
数据源切换工具类, 这里的核心是ThreadLocal<DataSourceType>
变量, ThreadLocal以前有过文档分析, 主要是用来维护线程内部变量的, 其中:
get()方法用来获取数据源
set()方法用来设置数据源
remove()用来清除数据源
@Configuration
@MapperScan(“jin.panpan.database.dao”)
public class MybatisConfig {
//默认数据源
@Primary
@Bean(“db1”)
@ConfigurationProperties(prefix = “spring.datasource.db1”)
public DataSource dataSource1(){
return DataSourceBuilder.create().build();
}
@Bean(“db2”)
@ConfigurationProperties(prefix = “spring.datasource.db2”)
public DataSource dataSource2(){
return DataSourceBuilder.create().build();
}
//动态数据源选择
@Bean
public DynamicDataSource dynamicDataSource(@Qualifier(“db1”) DataSource db1,
@Qualifier(“db2”) DataSource db2){
Map<Object, Object> map = new HashMap<>();
//此处的key 要和DynamicDataSource类的determineCurrentLookupKey方法返回值一致
map.put(DataSourceType.DB1.getDatabase(), db1);
map.put(DataSourceType.DB2.getDatabase(), db2);
DynamicDataSource dynamicDataSource = new DynamicDataSource();
dynamicDataSource.setTargetDataSources(map);
//设置默认数据库, 选择的数据库Bean注入时要带@Primary注释
dynamicDataSource.setDefaultTargetDataSource(db1);
return dynamicDataSource;
}
//会话工厂配置
@Bean
public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(dynamicDataSource);
Resource[] resources = new PathMatchingResourcePatternResolver()
.getResources(“classpath:mappers/*xml”);
factoryBean.setMapperLocations(resources);
return factoryBean.getObject();
}
//事务管理配置
@Bean
public PlatformTransactionManager transactionManager(DynamicDataSource dynamicDataSource){
return new DataSourceTransactionManager(dynamicDataSource);
}
}
复制代码
本类主要用来配置和注入mybatis相关配置bean, 主要有下面几步:
@MapperScan(“jin.panpan.database.dao”)
一般常规配置, 如果不配置多数据源, 一般是在入口类上注解
@ConfigurationProperties 导入配置文件里的配置
@Bean 指定数据源名称
@Primary 标记默认数据源
加载多个数据源, 如果需要的话, 指定默认数据源
需要注意数据源容器Map的key要和DataSourceType里的字段值一致, 否则无法切换
单数据源时, 一般无需手动配置; 多数据源时, 需要手动指定会话工厂, 但是配置是模式化的
事务管理的配置也是模式化的, 一般无特殊处理之处
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);
@Override
protected Object determineCurrentLookupKey() {
String database = DataSourceUtil.get() == null ? null : DataSourceUtil.get().getDatabase();
logger.info(“DynamicDataSource, 动态数据源返回={}”, database);
return database;
}
}
复制代码
此类其实是动态路由数据源的核心类, 扩展AbstractRoutingDataSource类, 重写determineCurrentLookupKey方法, determineCurrentLookupKey方法的返回值就是动态数据源, 返回值需要和配置文件及MybatisConfig里的一一对应.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface DataSource {
DataSourceType value() default DataSourceType.NONE;
}
复制代码
DataSource是一个方法注解, 用来作为数据源切换切入点, 此处可以使用类注解或者直接正则织入想监控的点
DataSourceAspect是注解的实现, 是核心实现
@Aspect
@Component
public class DataSourceAspect {
private static final Logger logger = LoggerFactory.getLogger(DataSourceAspect.class);
@Pointcut(“@annotation(jin.panpan.database.dynamic.datasource.annotate.DataSource)”)
public void pointCut() {
}
@SneakyThrows
@Around(“pointCut()”)
public Object around(ProceedingJoinPoint pjp) {
//数据源
DataSourceType dataSourceType = null;
//方法对象
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
//注释
DataSource dynamicDataSource = method.getAnnotation(DataSource.class);
String path = null;
//注释中指定数据源, 则使用数据库中的数据源
if(dynamicDataSource.value()!=null && dynamicDataSource.value() != DataSourceType.NONE){
dataSourceType = dynamicDataSource.value();
}
//否则从请求路径中获取
if(dataSourceType == null){
HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
path = request.getRequestURL().toString();
//TODO 待优化 需截取域名进行检查
if(path.contains(DataSourceType.DB1.getDatabase())){
dataSourceType = DataSourceType.DB1;
}
if(path.contains(DataSourceType.DB2.getDatabase())){
dataSourceType = DataSourceType.DB2;
}
}
logger.info(“DataSource, 方法={}, 数据源={}, 路径={}, 注释自带数据源={}”,
method.getName(), dataSourceType==null ? null : dataSourceType.getDatabase(),
path, dynamicDataSource.value());
if(dataSourceType == null){
throw new Exception(“非法数据源”);
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
很多程序员,整天沉浸在业务代码的 CRUD 中,业务中没有大量数据做并发,缺少实战经验,对并发仅仅停留在了解,做不到精通,所以总是与大厂擦肩而过。
我把私藏的这套并发体系的笔记和思维脑图分享出来,理论知识与项目实战的结合,我觉得只要你肯花时间用心学完这些,一定可以快速掌握并发编程。
不管是查缺补漏还是深度学习都能有非常不错的成效,需要的话记得帮忙点个赞支持一下
整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
、讲解视频,并且会持续更新!**
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
很多程序员,整天沉浸在业务代码的 CRUD 中,业务中没有大量数据做并发,缺少实战经验,对并发仅仅停留在了解,做不到精通,所以总是与大厂擦肩而过。
我把私藏的这套并发体系的笔记和思维脑图分享出来,理论知识与项目实战的结合,我觉得只要你肯花时间用心学完这些,一定可以快速掌握并发编程。
不管是查缺补漏还是深度学习都能有非常不错的成效,需要的话记得帮忙点个赞支持一下
整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。