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

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

數(shù)據(jù)源管理|主從庫(kù)動(dòng)態(tài)路由,AOP模式讀寫分離

本文源碼: GitHub·點(diǎn)這里 || GitEE·點(diǎn)這里

成都創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的淥口網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!

一、多數(shù)據(jù)源應(yīng)用

1、基礎(chǔ)描述

在相對(duì)復(fù)雜的應(yīng)用服務(wù)中,配置多個(gè)數(shù)據(jù)源是常見(jiàn)現(xiàn)象,例如常見(jiàn)的:配置主從數(shù)據(jù)庫(kù)用來(lái)寫數(shù)據(jù),再配置一個(gè)從庫(kù)讀數(shù)據(jù),這種讀寫分離模式可以緩解數(shù)據(jù)庫(kù)壓力,提高系統(tǒng)的并發(fā)能力和穩(wěn)定性,執(zhí)行效率。

數(shù)據(jù)源管理 | 主從庫(kù)動(dòng)態(tài)路由,AOP模式讀寫分離

2、核心API

在處理這種常見(jiàn)問(wèn)題,要學(xué)會(huì)查詢服務(wù)基礎(chǔ)框架的API,說(shuō)直白點(diǎn)就是查詢Spring框架的API(工作幾年,還沒(méi)用過(guò)Spring之外的框架搭建環(huán)境),這種常用的業(yè)務(wù)模式,基本上Spring都提供了API支持。

核心API:AbstractRoutingDataSource

底層維護(hù)Map容器,用來(lái)保存數(shù)據(jù)源集合,提供一個(gè)抽象方法,實(shí)現(xiàn)自定義的路由策略。

@Nullable
private Map resolvedDataSources;
@Nullable
protected abstract Object determineCurrentLookupKey();

補(bǔ)刀一句:為何框架的原理很難通過(guò)一篇文章看明白?因?yàn)槭褂玫牟欢啵疽庾R(shí)沒(méi)有形成,熟悉框架原理的基本要求:對(duì)框架的各種功能都熟悉,經(jīng)常使用,自然而然的就明白了,鹽大曬的久,咸魚才夠味。

二、數(shù)據(jù)源路由

1、數(shù)據(jù)源管理

配置兩個(gè)數(shù)據(jù)源

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.MySQL.jdbc.Driver
    master:
      url: jdbc:mysql://localhost:3306/data_master
      username: root
      password: 123456
    slave:
      url: jdbc:mysql://localhost:3306/data_slave
      username: root
      password: 123456

從實(shí)際開(kāi)發(fā)角度,這兩個(gè)數(shù)據(jù)源需要配置主從復(fù)制流程,再基于安全角度,寫庫(kù)可以只給寫權(quán)限,讀庫(kù)只給讀權(quán)限。

Map容器加載

@Configuration
public class DruidConfig {
    // 忽略參數(shù)加載,源碼中有
    @Bean
    @Primary
    public DataSource primaryDataSource() {
        Map map = new HashMap<>();
        map.put("masterDataSource", masterDataSource());
        map.put("slaveDataSource", slaveDataSource());
        RouteDataSource routeDataSource = new RouteDataSource();
        routeDataSource.setTargetDataSources(map);
        routeDataSource.setDefaultTargetDataSource(masterDataSource());
        return routeDataSource ;
    }
    private DataSource masterDataSource() {
        return getDefDataSource(masterUrl,masterUsername,masterPassword);
    }
    private DataSource slaveDataSource() {
        return getDefDataSource(slaveUrl,slaveUsername,slavePassword);
    }
    private DataSource getDefDataSource (String url,String userName,String passWord){
        DruidDataSource datasource = new DruidDataSource();
        datasource.setDriverClassName(driverClassName);
        datasource.setUrl(url);
        datasource.setUsername(userName);
        datasource.setPassword(passWord);
        return datasource;
    }
}

這里的Map容器管理兩個(gè)key,masterDataSource和slaveDataSource代表兩個(gè)不同的庫(kù),使用不同的key即加載對(duì)應(yīng)的庫(kù)。

2、容器Key管理

使用ThreadLocal管理當(dāng)前會(huì)會(huì)話中線程參數(shù),存取使用極其方便。

public class RouteContext implements AutoCloseable {
    private static final ThreadLocal threadLocal = new ThreadLocal<>();
    public static void setRouteKey (String key){
        threadLocal.set(key);
    }
    public static String getRouteKey() {
        String key = threadLocal.get();
        return key == null ? "masterDataSource" : key;
    }
    @Override
    public void close() {
        threadLocal.remove();
    }
}

3、路由Key實(shí)現(xiàn)

獲取ThreadLocal中,當(dāng)前數(shù)據(jù)源的key,適配相關(guān)聯(lián)的數(shù)據(jù)源。

public class RouteDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return RouteContext.getRouteKey();
    }
}

三、讀寫分離

1、AOP思維

基于AOP的切面思想,不同的方法類型,去設(shè)置對(duì)應(yīng)路由Key,這樣就可以在業(yè)務(wù)邏輯執(zhí)行之前,切換到不同的數(shù)據(jù)源。

Aspect
@Component
@Order(1)
public class ReadWriteAop {
    private static Logger LOGGER = LoggerFactory.getLogger(ReadWriteAop.class) ;
    @Before("execution(* com.master.slave.controller.*.*(..))")
    public void setReadDataSourceType() {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String method = request.getRequestURI() ;
        boolean rwFlag = readOrWrite(method) ;
        if (rwFlag){
            RouteContext.setRouteKey("slaveDataSource");
        } else {
            RouteContext.setRouteKey("masterDataSource");
        }
        LOGGER.info("請(qǐng)求方法:"+method+";執(zhí)行庫(kù):"+RouteContext.getRouteKey());
    }
    private String[] readArr = new String[]{"select","count","query","get","find"} ;
    private boolean readOrWrite (String method){
        for (String readVar:readArr) {
            if (method.contains(readVar)){
                return true ;
            }
        }
        return false ;
    }
}

常見(jiàn)的讀取方法:select、count、query、get、find等等,方法的命名要遵循自定義的路由規(guī)則。

2、提供測(cè)試接口

控制層API

import com.master.slave.entity.User;
import com.master.slave.service.UserService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class UserController {
    @Resource
    private UserService userService ;
    @GetMapping("/selectById")
    public User selectById (@RequestParam("id") Integer id) {
        return userService.selectById(id) ;
    }
    @GetMapping("/insert")
    public String insert () {
        User user = new User("張三","write") ;
        userService.insert(user) ;
        return "success" ;
    }
}

服務(wù)實(shí)現(xiàn)

@Service
public class UserService {
    @Resource
    private UserMapper userMapper ;
    public User selectById (Integer id) {
        return userMapper.selectById(id) ;
    }
    public void insert (User user){
        userMapper.insert(user);
    }
}

這樣數(shù)據(jù)源基于不同的類型方法就會(huì)一直的動(dòng)態(tài)切換。

四、源代碼地址

GitHub·地址
https://github.com/cicadasmile/data-manage-parent
GitEE·地址
https://gitee.com/cicadasmile/data-manage-parent

當(dāng)前題目:數(shù)據(jù)源管理|主從庫(kù)動(dòng)態(tài)路由,AOP模式讀寫分離
當(dāng)前路徑:http://weahome.cn/article/jicodo.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部