spring学习笔记(19)mysql读写分离后端AOP控制实例

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: <div class="markdown_views"><p>在这里,我们接上一篇文章,利用JNDI访问应用服务器配置的两个数据源来模拟同时操作不同的数据库如同时操作mysql和oracle等。实际上,上个例子可能用来模拟mysql数据库主从配置读写分离更贴切些。既然如此,在本例中,我们就完成读写分离的模拟在web端的配置实例。</p><p>续上次的例子,关于JNDI数据

在这里,我们接上一篇文章,利用JNDI访问应用服务器配置的两个数据源来模拟同时操作不同的数据库如同时操作mysql和oracle等。实际上,上个例子可能用来模拟mysql数据库主从配置读写分离更贴切些。既然如此,在本例中,我们就完成读写分离的模拟在web端的配置实例。

续上次的例子,关于JNDI数据源的配置和spring datasource的配置这里不再重复。下面着重加入AOP实现DAO层动态分库调用。可先看上篇文章《spring学习笔记(18)使用JNDI模拟访问应用服务器多数据源实例 》

1. DAO层设计

/***************接口设计************/
public interface MyBaseDao {
    SessionFactory getSessionFactory();
    <E> E add(Object object);
    <E>E queryUnique(Class<E> clazz, Integer entityId);
    void setSourceType(Integer sourceType);
}
/****************实现类设计******************/
@Repository
public class MyBaseDaoImpl implements MyBaseDao{
    //由于本类是单例了,考虑到线程安全问题,这是使用ThreadLocal作为判断调用哪个数据源的依据
    private ThreadLocal<Integer> sourceType = new ThreadLocal<Integer>();
    @Autowired
    @Qualifier("sessionFactory")
    private SessionFactory sessionFactory;

    @Autowired
    @Qualifier("sessionFactory2")
    private SessionFactory sessionFactory2;

    @Override
    public SessionFactory getSessionFactory() {
        if(sourceType.get() == null){//如果没有值则默认使用数据源1
            sourceType.set(1);
        }
        switch (sourceType.get()) {
        case 1://使用数据源1,本例中这里是主库,主要负责写
            return sessionFactory;
        case 2: //使用数据源2,本例中这里是从库,主要负责读
            return sessionFactory2;
        default:
            throw new IllegalArgumentException("unknown sourceType");
        }
    }
    @Override//模拟一个写的操作,要让主库数据源调用
    public <E> E add(Object object) {
        return (E) getSessionFactory().openSession().save(object);
    }
    @Override//模拟一个读的操作,要让从库数据源调用
    public <E> E queryUnique(Class<E> clazz, Integer entityId) {
        return (E) getSessionFactory().openSession().get(clazz, entityId);
    }
    @Override//共AOP增强类修改数据源类型
    public void setSourceType(Integer sourceType) {
        this.sourceType.set(sourceType);
    }
}

2. AOP类设计

@Aspect
public class DataSourceSelector {//使用前置增强
    @Before("execution( * com.yc.dao.MyBaseDaoImpl.add*(..))")//写操作
    public void before1(JoinPoint joinPoint){
        ((MyBaseDao)joinPoint.getTarget()).setSourceType(1);//切换到主库
    }

    @Before("execution( * com.yc.dao.MyBaseDaoImpl.query*(..))")//读操作
    public void before2(JoinPoint joinPoint){
        ((MyBaseDao)joinPoint.getTarget()).setSourceType(2);//切换到从库
    }
}

关于AOP的配置教程,可移步参考本系列前面AOP部分的文章。然后我们还需要在IOC容器中注册我们的切面。

<aop:aspectj-autoproxy />   <!-- 使@AspectJ注解生效 -->
<bean class="com.yc.aop.DataSourceSelector" /><!-- 注册切面 -->

3. 修改控制器

针对上一篇文章的控制器,作如下修改:

@Controller
public class JNDITestController {

    @Autowired
    private MyBaseDao myBaseDao;

    @RequestMapping("testJNDI")
    @ResponseBody
    public Object testJNDI(){
        User user = new User();
        user.setName("new_user_fron_yc1");
        Integer newId = myBaseDao.add(user);
        System.out.println("new UserId = " + newId);//获取我们新插入的id
        System.out.println("is new User here? " + myBaseDao.queryUnique(com.yc.model2.User.class, newId));
        return newId;
    }
}

4. 测试与结果分析

运行服务器,然后在游览器中输入http://localhost:8090/yc/testJNDI,我们会看到控制台打印信息:

new UserId = 4
is new User here? null

newUserId是我们插入到主库中的,id为4。
但我们紧接着读取,却并未读取到。这说明我们存的数据库和读的数据库并不是同一个,从而简单地实现了读写分离。为了验证这一点,我们所示数据库,如下图所示,显然我们在yc1存进去了我们的测试数据,在yc2中并没有!
这里写图片描述

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
1月前
|
监控 Java 数据处理
【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解
【Spring云原生】Spring Batch:海量数据高并发任务处理!数据处理纵享新丝滑!事务管理机制+并行处理+实例应用讲解
|
2月前
|
监控 数据可视化 关系型数据库
微服务架构+Java+Spring Cloud +UniApp +MySql智慧工地系统源码
项目管理:项目名称、施工单位名称、项目地址、项目地址、总造价、总面积、施工准可证、开工日期、计划竣工日期、项目状态等。
307 6
|
3月前
|
存储 关系型数据库 MySQL
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
Linux C/C++ 开发(学习笔记八):Mysql数据库图片存储
50 0
|
1天前
|
SQL 关系型数据库 MySQL
Spring_jdbc数据连接池(mysql实现增、删、改、查)
Spring_jdbc数据连接池(mysql实现增、删、改、查)
6 0
|
1天前
|
安全 Java Maven
[AIGC] Spring Boot中的切面编程和实例演示
[AIGC] Spring Boot中的切面编程和实例演示
|
8天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
12天前
|
存储 关系型数据库 MySQL
【后端面经】【数据库与MySQL】为什么MySQL用B+树而不用B树?-02
【4月更文挑战第11天】数据库索引使用规则:`AND`用`OR`不用,正用反不用,范围中断。索引带来空间和内存代价,包括额外磁盘空间、内存占用和数据修改时的维护成本。面试中可能涉及B+树、聚簇索引、覆盖索引等知识点。MySQL采用B+树,因其利于范围查询和内存效率。数据库不使用索引可能因`!=`、`LIKE`、字段区分度低、特殊表达式或全表扫描更快。索引与NULL值处理在不同数据库中有差异,MySQL允许NULL在索引中的使用。
17 3
|
2月前
|
关系型数据库 MySQL
MySQL学习笔记
MySQL学习笔记
|
2月前
|
安全 关系型数据库 MySQL
某教程学习笔记(一):09、MYSQL数据库漏洞
某教程学习笔记(一):09、MYSQL数据库漏洞
19 0
|
2月前
|
存储 关系型数据库 MySQL
《高性能Mysql》学习笔记(二)
《高性能Mysql》学习笔记(二)
136 0