真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

spring-boot結(jié)合AOP實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)配置的方法

本篇內(nèi)容主要講解“spring-boot結(jié)合AOP實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)配置的方法”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“spring-boot結(jié)合AOP實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)配置的方法”吧!

網(wǎng)站建設(shè)哪家好,找創(chuàng)新互聯(lián)建站!專注于網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開發(fā)、微信小程序開發(fā)、集團(tuán)企業(yè)網(wǎng)站建設(shè)等服務(wù)項(xiàng)目。為回饋新老客戶創(chuàng)新互聯(lián)還提供了金秀免費(fèi)建站歡迎大家使用!

Spring-Boot+AOP方式實(shí)現(xiàn)多數(shù)據(jù)源切換

設(shè)計(jì)總體思路:Spring-Boot+AOP方式實(shí)現(xiàn)多數(shù)據(jù)源切換,繼承AbstractRoutingDataSource實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)的獲取,在service層使用注解指定數(shù)據(jù)源。

一、多數(shù)據(jù)源配置

在application.properties中,我們的配置是這樣的

#主數(shù)據(jù)源
druid.master.url=jdbc:MySQL://url/masterdb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
druid.master.username=xxx
druid.master.password=123
druid.master.driver-class-name=com.mysql.jdbc.Driver
druid.master.max-wait=5000
druid.master.max-active=100
druid.master.test-on-borrow=true
druid.master.validation-query=SELECT 1

#從數(shù)據(jù)源
druid.slave.url=jdbc:mysql://url/slavedb?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull
druid.slave.username=xxx
druid.slave.password=123
druid.slave.driver-class-name=com.mysql.jdbc.Driver
druid.slave.max-wait=5000
druid.slave.max-active=100
druid.slave.test-on-borrow=true
druid.slave.validation-query=SELECT 1

讀取配置



    
    
    
    
    
    
    
    
    
    
    





    
    
    
    
    

    
    
    
    
    
    




    
        
            
            
        
    
    




    




    



    






    
    



    
    
二、動(dòng)態(tài)數(shù)據(jù)源

spring為我們提供了AbstractRoutingDataSource,即帶路由的數(shù)據(jù)源。繼承后我們需要實(shí)現(xiàn)它的determineCurrentLookupKey(),該方法用于自定義實(shí)際數(shù)據(jù)源名稱的路由選擇方法,由于我們將信息保存到了ThreadLocal中,所以只需要從中拿出來即可。

public class DynamicDataSource extends AbstractRoutingDataSource {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Override
    protected Object determineCurrentLookupKey() {
        String dataSource = JdbcContextHolder.getDataSource();
        logger.info("數(shù)據(jù)源為{}",dataSource);
        return dataSource;
    }

}
三. 數(shù)據(jù)源動(dòng)態(tài)切換類

動(dòng)態(tài)數(shù)據(jù)源切換是基于AOP的,所以我們需要聲明一個(gè)AOP切面,并在切面前做數(shù)據(jù)源切換,切面完成后移除數(shù)據(jù)源名稱。

@Aspect
@Order(1)   //設(shè)置AOP執(zhí)行順序(需要在事務(wù)之前,否則事務(wù)只發(fā)生在默認(rèn)庫(kù)中)
@Component
public class DataSourceAspect {

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    //切點(diǎn)
    @Pointcut("execution(* com.xxx.service.*.*(..))")
    public void aspect() { }

    @Before("aspect()")
    private void before(JoinPoint point) {
        Object target = point.getTarget();
        String method = point.getSignature().getName();
        Class classz = target.getClass();// 獲取目標(biāo)類
        Class[] parameterTypes = ((MethodSignature) point.getSignature())
                .getMethod().getParameterTypes();
        try {
            Method m = classz.getMethod(method, parameterTypes);
            if (m != null && m.isAnnotationPresent(MyDataSource.class)) {
                MyDataSource data = m.getAnnotation(MyDataSource.class);
                logger.info("method :{},datasource:{}",m.getName() ,data.value().getName());
                JdbcContextHolder.putDataSource(data.value().getName());// 數(shù)據(jù)源放到當(dāng)前線程中
            }
        } catch (Exception e) {
            logger.error("get datasource error ",e);
            //默認(rèn)選擇master
            JdbcContextHolder.putDataSource(DataSourceType.Master.getName());// 數(shù)據(jù)源放到當(dāng)前線程中
        }

    }

    @AfterReturning("aspect()")
    public void after(JoinPoint point) {
        JdbcContextHolder.clearDataSource();
    }
}
四、數(shù)據(jù)源管理類
public class JdbcContextHolder {

    private final static ThreadLocal local = new ThreadLocal<>();

    public static void putDataSource(String name) {
        local.set(name);
    }

    public static String getDataSource() {
        return local.get();
    }

    public static void clearDataSource() {
        local.remove();
    }
}
五、數(shù)據(jù)源注解和枚舉

我們切換數(shù)據(jù)源時(shí),一般都是在調(diào)用具體接口的方法前實(shí)現(xiàn),所以我們定義一個(gè)方法注解,當(dāng)AOP檢測(cè)到方法上有該注解時(shí),根據(jù)注解中value對(duì)應(yīng)的名稱進(jìn)行切換。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyDataSource {

    DataSourceType value();

}

public enum  DataSourceType {
    // 主表
    Master("master"),
    // 從表
    Slave("slave");

    private String name;

    private DataSourceType(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
六、切點(diǎn)注解

由于我們的動(dòng)態(tài)數(shù)據(jù)源配置了默認(rèn)庫(kù),所以如果方法是操作默認(rèn)庫(kù)的可以不需要注解,如果要操作非默認(rèn)數(shù)據(jù)源,我們需要在方法上添加@MyDataSource("數(shù)據(jù)源名稱")注解,這樣就可以利用AOP實(shí)現(xiàn)動(dòng)態(tài)切換了

@Component
public class xxxServiceImpl {
    @Resource
    private XxxMapperExt xxxMapperExt;

    @MyDataSource(value= DataSourceType.Slave)
    public List getAll(){
        return xxxMapperExt.getAll();
    }

}

原文鏈接:

http://tech.dianwoda.com/2018/03/28/spring-boot-aopfang-shi-shi-xian-duo-shu-ju-yuan-qie-huan/

到此,相信大家對(duì)“spring-boot結(jié)合AOP實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)配置的方法”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


名稱欄目:spring-boot結(jié)合AOP實(shí)現(xiàn)數(shù)據(jù)源動(dòng)態(tài)配置的方法
網(wǎng)站路徑:http://weahome.cn/article/gssicg.html

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部