【java】不同内容动态多数据源案例解决方案
问题背景
公司为了规范信息管理,想要统一处理两个子公司员工的数据。这些信息原本分别由子公司各自管理,分别在不同的数据库,并且各自的内容规范不同。那么如何才能多个数据库共用一套业务代码,简化开发呢?
思路
我们可以设置多数据库源,通过代码动态设置目标数据源,同时数据接口调用业务时,根据数据源标识动态选择相应业务。
首先,在请求接口时可以通过向请求头绑定参数的形式指定目标数据库。
其次,在需要动态指定默认数据库的接口加注解标识。
然后,配置Aop扫描该注解,获取请求头中的数据源参数,设置目标数据库。
最后,在数据接口调用业务层切换工具类,根据数据源代码返回业务层对象。
技术方案
技术:Aop+ThreadLocal+AbstractRoutingDataSource
Aop:面向切面编程,用于统一获取请求头中的数据源参数。
ThreadLocal:本地线程变量,由于存放当次请求的数据源。
AbstractRoutingDataSource:多数据源接口类,通过继承该类重写determineCurrentLookupKey()方法来切换目标数据源
案例
目录指引
核心代码解析
代码大致与同内容多数据源案例相同,数据源切换可参考=>点我:多数据源案例,本篇主要讲解业务层切换逻辑。
1.多业务逻辑
一个业务接口多个业务实现方式
2. 将单一业务接口换成业务集合
List
<
EmployeeService>
employeeServices;
框架会自动将实现EmployeeService接口并带有@Service注解的类注入对象,接下来就可以根据情况动态切换业务层接口。
这里我将切换的代码抽取成了工具类。
@RestController
@RequestMapping("/emp")
public class EmployeeController {
//通过List集合装载同接口业务对象
@Autowired
private List<EmployeeService> employeeServices;
@ApiOperation("全部员工")
@CustomDynamicDbChange
@GetMapping
public R all(){
//这里通过工具类动态指定目标业务对象
EmployeeService employeeService = BusinessServiceUtils.getEmpService(employeeServices, CustomDynamicDataSourceContextHolder.getDataSourceType());
return employeeService.all();
}
}
3.业务切换工具类
业务切换的具体逻辑,通过接口内的enableDynamicDb方法判断是否是目标数据源。
@Slf4j
public class BusinessServiceUtils {
public static EmployeeService getEmpService(List<EmployeeService> employeeServices, String dataSourceType) {
Optional<EmployeeService> service = employeeServices.stream()
.filter(e -> e.enableDynamicDb(dataSourceType))
.findFirst();
if (!service.isPresent()) {
log.error("数据源编码:{},后台无对应的数据源处理service逻辑", dataSourceType);
throw new RuntimeException("无对应的数据源");
}
return service.get();
}
}
业务层判断是否为目标业务对象的代码逻辑,如下。