今天就跟大家聊聊有關(guān)如何在spring boot中利用mybatis實(shí)現(xiàn)多數(shù)據(jù)源切換,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
“真誠服務(wù),讓網(wǎng)絡(luò)創(chuàng)造價(jià)值”是我們的服務(wù)理念,創(chuàng)新互聯(lián)公司團(tuán)隊(duì)10年如一日始終堅(jiān)持在網(wǎng)站建設(shè)領(lǐng)域,為客戶提供優(yōu)質(zhì)服。不管你處于什么行業(yè),助你輕松跨入“互聯(lián)網(wǎng)+”時(shí)代,PC網(wǎng)站+手機(jī)網(wǎng)站+公眾號+重慶小程序開發(fā)。
1.首先定義一個(gè)注解類
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface TargetDataSource { String value();//此處接收的是數(shù)據(jù)源的名稱 }
2.然后建一個(gè)配置類,這個(gè)在項(xiàng)目啟動(dòng)時(shí)會加載數(shù)據(jù)源,一開始采用了HikariCP,查資料說是最快性能最好的,然后又發(fā)現(xiàn)了阿里的druid,這個(gè)功能比較全面,而且性能也還可以,最主要他還有監(jiān)控功能,具體實(shí)現(xiàn)看如下代碼
package com.example.demo.datasource; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; import com.example.demo.datasource.DynamicDataSource; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.transaction.PlatformTransactionManager; import org.w3c.dom.NodeList; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.sql.DataSource; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.io.File; import com.alibaba.druid.support.http.StatViewServlet; /** * Author: wangchao * Version: * Date: 2017/9/11 * Description:數(shù)據(jù)源配置 * Modification History: * Date Author Version Description * -------------------------------------------------------------- * Why & What is modified: */ @Configuration @EnableScheduling public class DataSourceConfig { /*@Autowired private DBProperties properties;*/ @Value("${datasource.filePath}") private String filePath;//數(shù)據(jù)源配置 @Bean(name = "dataSource") public DataSource dataSource() { //按照目標(biāo)數(shù)據(jù)源名稱和目標(biāo)數(shù)據(jù)源對象的映射存放在Map中 Map
3.動(dòng)態(tài)數(shù)據(jù)源,從之前已加載的數(shù)據(jù)源中選取,DynamicDataSource和DynamicDataSourceHolder配合使用
public class DynamicDataSource extends AbstractRoutingDataSource{ //數(shù)據(jù)源路由,此方用于產(chǎn)生要選取的數(shù)據(jù)源邏輯名稱 @Override protected Object determineCurrentLookupKey() { //從共享線程中獲取數(shù)據(jù)源名稱 return DynamicDataSourceHolder.getDataSource(); } } public class DynamicDataSourceHolder { /** * 本地線程共享對象 */ private static final ThreadLocalTHREAD_LOCAL = new ThreadLocal<>(); public static void putDataSource(String name) { THREAD_LOCAL.set(name); } public static String getDataSource() { return THREAD_LOCAL.get(); } public static void removeDataSource() { THREAD_LOCAL.remove(); } }
4.就是使用aop,在dao層切換數(shù)據(jù)源
@Component @Aspect public class DataSourceAspect { //切換放在mapper接口的方法上,所以這里要配置AOP切面的切入點(diǎn) @Pointcut("execution( * com.example.demo.dao.*.*(..))") public void dataSourcePointCut() { } @Before("dataSourcePointCut()") public void before(JoinPoint joinPoint) { Object target = joinPoint.getTarget(); String method = joinPoint.getSignature().getName(); Class<?>[] clazz = target.getClass().getInterfaces(); Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes(); try { Method m = clazz[0].getMethod(method, parameterTypes); //如果方法上存在切換數(shù)據(jù)源的注解,則根據(jù)注解內(nèi)容進(jìn)行數(shù)據(jù)源切換 if (m != null && m.isAnnotationPresent(TargetDataSource.class)) { TargetDataSource data = m.getAnnotation(TargetDataSource.class); String dataSourceName = data.value(); DynamicDataSourceHolder.putDataSource(dataSourceName); } else { } } catch (Exception e) { } } //執(zhí)行完切面后,將線程共享中的數(shù)據(jù)源名稱清空 @After("dataSourcePointCut()") public void after(JoinPoint joinPoint){ DynamicDataSourceHolder.removeDataSource(); } }
數(shù)據(jù)連接都配置在xml里面
xml路徑在配置文件里面配置,這樣適用讀寫分離和多個(gè)不同的數(shù)據(jù)源,而且多個(gè)項(xiàng)目可以共用這一個(gè)配置
最后引用注解,需要注意的是注解的數(shù)據(jù)庫名稱和xml里面databasename節(jié)點(diǎn)是一一對應(yīng)的,可以隨便自定義,比如讀寫是一個(gè)數(shù)據(jù)庫名字,這時(shí)候就可以定義成pringtest_r表示讀庫
看完上述內(nèi)容,你們對如何在spring boot中利用mybatis實(shí)現(xiàn)多數(shù)據(jù)源切換有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。