這篇文章運(yùn)用了實(shí)例代碼展示springboot動(dòng)態(tài)數(shù)據(jù)源的使用方法,代碼非常詳細(xì),可供感興趣的小伙伴們參考借鑒,希望對(duì)大家有所幫助。
創(chuàng)新互聯(lián)建站,為您提供網(wǎng)站建設(shè)公司、成都網(wǎng)站制作、網(wǎng)站營銷推廣、網(wǎng)站開發(fā)設(shè)計(jì),對(duì)服務(wù)成都宣傳片制作等多個(gè)行業(yè)擁有豐富的網(wǎng)站建設(shè)及推廣經(jīng)驗(yàn)。創(chuàng)新互聯(lián)建站網(wǎng)站建設(shè)公司成立于2013年,提供專業(yè)網(wǎng)站制作報(bào)價(jià)服務(wù),我們深知市場的競爭激烈,認(rèn)真對(duì)待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進(jìn)步,是我們永遠(yuǎn)的責(zé)任!
我們的數(shù)據(jù)庫A為主庫,其他數(shù)據(jù)庫配置在主庫中,從庫B,C,D的數(shù)量是不固定的,會(huì)根據(jù)業(yè)務(wù)的需要?jiǎng)討B(tài)的把配置寫入到主庫中并動(dòng)態(tài)在創(chuàng)建新的數(shù)據(jù)庫,也就是說在項(xiàng)目中我們只需要配置主庫的數(shù)據(jù)源,其他從庫都需要從主庫中讀出配置并動(dòng)態(tài)創(chuàng)建數(shù)據(jù)源,動(dòng)態(tài)的注入到Spring容器中,在使用的時(shí)候動(dòng)態(tài)的切換數(shù)據(jù)源以實(shí)現(xiàn)相應(yīng)的功能邏輯
Springboot:2.0.4
Mybatis-plus:3.0.7.1
JDK:1.8
在啟動(dòng)類添加@Import({DynamicDataSourceRegister.class})注解用于代替默認(rèn)的數(shù)據(jù)源配置
代碼結(jié)構(gòu)如下:
@Component
public class ApplicationContextUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextUtil.applicationContext = applicationContext;
}
/**
* 取得存儲(chǔ)在靜態(tài)變量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
checkApplicationContext();
return applicationContext;
}
/**
* 從靜態(tài)變量ApplicationContext中取得Bean, 自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類型.
*/
public static <T> T getBean(String name) {
checkApplicationContext();
if (applicationContext.containsBean(name)) {
return (T) applicationContext.getBean(name);
}
return null;
}
/**
* 從靜態(tài)變量ApplicationContext中取得Bean, 自動(dòng)轉(zhuǎn)型為所賦值對(duì)象的類型.
*/
public static <T> T getBean(Class<T> clazz) {
checkApplicationContext();
return (T) applicationContext.getBeansOfType(clazz);
}
private static void checkApplicationContext() {
if (applicationContext == null)
throw new IllegalStateException("applicaitonContext未注入,請(qǐng)?jiān)赼pplicationContext.xml中定義SpringContextUtil");
}
public synchronized static void registerSingletonBean(String beanName,Class clzz,Map<String,Object> original) {
checkApplicationContext();
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ApplicationContextUtil.getApplicationContext().getAutowireCapableBeanFactory();
if(beanFactory.containsBean(beanName)){
removeBean(beanName);
}
GenericBeanDefinition definition = new GenericBeanDefinition();
//類class
definition.setBeanClass(clzz);
//屬性賦值
definition.setPropertyValues(new MutablePropertyValues(original));
//注冊(cè)到spring上下文
beanFactory.registerBeanDefinition(beanName, definition);
}
public synchronized static void registerSingletonBean(String beanName, Object obj, Map<String,Object> original) {
checkApplicationContext();
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) ApplicationContextUtil.getApplicationContext().getAutowireCapableBeanFactory();
if(beanFactory.containsBean(beanName)){
removeBean(beanName);
}
GenericBeanDefinition definition = new GenericBeanDefinition();
//類class
definition.setBeanClass(obj.getClass());
//屬性賦值
definition.setPropertyValues(new MutablePropertyValues(original));
//注冊(cè)到spring上下文
beanFactory.registerBeanDefinition(beanName, definition);
}
public synchronized static void registerSingletonBean(String beanName,Object obj) {
registerSingletonBean(beanName,obj,BeanUtils.transBean2Map(obj));
}
/**
* 刪除spring中管理的bean
* @param beanName
*/
public static void removeBean(String beanName){
ApplicationContext ctx = ApplicationContextUtil.getApplicationContext();
DefaultListableBeanFactory acf = (DefaultListableBeanFactory) ctx.getAutowireCapableBeanFactory();
if(acf.containsBean(beanName)) {
acf.removeBeanDefinition(beanName);
}
}
}
public class BeanUtils {
public static Map<String, Object> transBean2Map(Object obj) {
if(obj == null){
return null;
}
Map<String, Object> map = new HashMap<>();
try {
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
String key = property.getName();
// 過濾class屬性
if (!key.equals("class")) {
// 得到property對(duì)應(yīng)的getter方法
Method getter = property.getReadMethod();
Object value = getter.invoke(obj);
map.put(key, value);
}
}
} catch (IntrospectionException | InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
return map;
}
}
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSourceType();
}
public void updateTargetDataSource(Map<String,DataSource> customDataSources){
Map<Object,Object> customDS=new HashMap<Object, Object>();
customDS.putAll(customDataSources);
setTargetDataSources(customDS);
afterPropertiesSet();
}
}
public class DynamicDataSourceContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static List<String> dataSourceIds = new ArrayList<>();
public static String getDataSourceType() {
return contextHolder.get();
}
public static void setDataSourceType(String dataSourceType) {
if(!containsDataSource(dataSourceType)){
DynamicDataSourceRegister.addSlaveDataSource(dataSourceType);
}
contextHolder.set(dataSourceType);
}
public static void clearDataSourceType() {
contextHolder.remove();
}
/**
* 判斷指定DataSrouce當(dāng)前是否存在
*/
public static boolean containsDataSource(String dataSourceId) {
return dataSourceIds.contains(dataSourceId);
}
}
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceRegister.class);
//默認(rèn)數(shù)據(jù)源
public static DataSource defaultDataSource;
//用戶自定義數(shù)據(jù)源
public static Map<String, DataSource> slaveDataSources = new HashMap<>();
public static BeanDefinitionRegistry beanDefinitionRegistry=null;
public static String driverName;
public static String userName;
public static String password;
public static String type;
public static String url;
@Override
public void setEnvironment(Environment environment) {
initDefaultDataSource(environment);
}
private void initDefaultDataSource(Environment env) {
// 讀取主數(shù)據(jù)源
driverName=env.getProperty("spring.datasource.driver-class-name");
userName=env.getProperty("spring.datasource.username");
password=env.getProperty("spring.datasource.password");
type=env.getProperty("spring.datasource.type");
url=env.getProperty("spring.datasource.url");
Constant.defaultDbName="a";
Map<String, Object> dsMap = new HashMap<>();
dsMap.put("driver",driverName);
dsMap.put("url",url);
dsMap.put("username",userName);
dsMap.put("password",password);
dsMap.put("type",type);
defaultDataSource = buildDataSource(dsMap);
}
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
DynamicDataSourceContextHolder.dataSourceIds.add("dataSource");
Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
//添加默認(rèn)數(shù)據(jù)源
targetDataSources.put("dataSource", this.defaultDataSource);
this.beanDefinitionRegistry=beanDefinitionRegistry;
beanDefinitionRegistry(defaultDataSource,targetDataSources);
logger.info("Dynamic DataSource Registry");
}
public static void addSlaveDataSource(String dataSourceType){
BeanDefinition beanDefinition=beanDefinitionRegistry.getBeanDefinition("dataSource");
PropertyValue propertyValue=beanDefinition.getPropertyValues().getPropertyValue("targetDataSources");
Map<String,DataSource> oldTargetDataSource=(Map<String,DataSource>) propertyValue.getValue();
String newUrl=firstStr+dataSourceType+secondStr;
Map<String, Object> dsMap = new HashMap<>();
dsMap.put("driver",driverName);
dsMap.put("url",newUrl);
dsMap.put("username",userName);
dsMap.put("password",password);
dsMap.put("type",type);
DataSource ds = buildDataSource(dsMap);
oldTargetDataSource.put(dataSourceType,ds);
DynamicDataSource dynamicDataSource =ApplicationContextUtil.getBean("dataSource");
dynamicDataSource.updateTargetDataSource(oldTargetDataSource);
DynamicDataSourceContextHolder.dataSourceIds.add(dataSourceType);
}
public void beanDefinitionRegistry(DataSource defaultDataSource,Map<Object,Object> targetDataSources){
//創(chuàng)建DynamicDataSource
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(DynamicDataSource.class);
beanDefinition.setSynthetic(true);
MutablePropertyValues mpv = beanDefinition.getPropertyValues();
mpv.addPropertyValue("defaultTargetDataSource", defaultDataSource);
if(targetDataSources.size()>0){
mpv.addPropertyValue("targetDataSources", targetDataSources);
}
//注冊(cè) - BeanDefinitionRegistry
beanDefinitionRegistry.registerBeanDefinition("dataSource", beanDefinition);
}
public static DataSource buildDataSource(Map<String, Object> dataSourceMap) {
try {
Object type = dataSourceMap.get("type");
Class<? extends DataSource> dataSourceType;
dataSourceType = (Class<? extends DataSource>) Class.forName((String) type);
String driverClassName = dataSourceMap.get("driver").toString();
String url = dataSourceMap.get("url").toString();
String username = dataSourceMap.get("username").toString();
String password = dataSourceMap.get("password").toString();
// 自定義DataSource配置
DataSourceBuilder factory = DataSourceBuilder.create().driverClassName(driverClassName).url(url)
.username(username).password(password).type(dataSourceType);
return factory.build();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
DynamicDataSourceContextHolder.setDataSourceType("B");
Integer lProductUv=dataVisitCollectionMapper.getProductUv(dDate);
DynamicDataSourceContextHolder.setDataSourceType(Constant.defaultDbName);
在setDataSourceType的時(shí)候判斷是否存在此數(shù)據(jù)源,如果存在就直接切換,不存在就動(dòng)態(tài)創(chuàng)建并加入到Spring容器中,從而實(shí)現(xiàn)動(dòng)態(tài)創(chuàng)建數(shù)據(jù)源的目的
關(guān)于springboot動(dòng)態(tài)數(shù)據(jù)源的使用就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
當(dāng)前題目:springboot動(dòng)態(tài)數(shù)據(jù)源的使用
分享網(wǎng)址:http://m.rwnh.cn/article20/gspjco.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站導(dǎo)航、品牌網(wǎng)站制作、搜索引擎優(yōu)化、網(wǎng)站收錄、網(wǎng)站建設(shè)、網(wǎng)站排名
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)