SpringBoot和Mycat动态数据源项目整合
SpringBoot项目整合动态数据源(读写分离)
1.配置多个数据源,根据业务需求访问不同的数据,指定对应的策略:增加,删除,修改操作访问对应数据,查询访问对应数据,不同数据库做好的数据一致性的处理。由于此方法相对易懂,简单,不做过多介绍。 
2. 动态切换数据源,根据配置的文件,业务动态切换访问的数据库:此方案通过Spring的AOP,AspactJ来实现动态织入,通过编程继承实现Spring中的AbstractRoutingDataSource,来实现数据库访问的动态切换,不仅可以方便扩展,不影响现有程序,而且对于此功能的增删也比较容易。 
3. 通过mycat来实现读写分离:使用mycat提供的读写分离功能,mycat连接多个数据库,数据源只需要连接mycat,对于开发人员而言他还是连接了一个数据库(实际是mysql的mycat中间件),而且也不需要根据不同 业务来选择不同的库,这样就不会有多余的代码产生。
详细参考配置
动态数据源核心配置
在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上。
1.项目中需要集成多个数据源分别为读和写的数据源,绑定不同的key。
2.采用AOP技术进行拦截业务逻辑层方法,判断方法的前缀是否需要写或者读的操作
3.如果方法的前缀是写的操作的时候,直接切换为写的数据源,反之切换为读的数据源
也可以自己定义注解进行封装
项目中有两个数据源 分别为读和写的数据源
使用AOP技术判断业务逻辑方法的前缀,如果前缀为比如select get find等。直接走RoutingDataSource
如果是写的话,传递一个key给RoutingDataSource指明使用写的数据源
下面是两个数据源,读的数据源和写的数据源。都需要设置一个key。然后注册存放到RoutingDataSource。
使用AOP技术拦截业务逻辑层的方法,判断方法的前缀是否为读或者写的操作
如果是写的操作,会给RoutingDataSource传递一个key 哈哈懂得了吧

环境配置:
1.创建读和写的数据源
2.将读和写的数据源注册到RoutiongDataSource
3.使用AOP技术拦截业务逻辑层,判断方法的前缀是否需要做读或者写
pom:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency> <dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.23</version>
</dependency>
</dependencies> <build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
配置代码:
通过ThreadLocal 保存本地多数据源
@Component
@Lazy(false)
public class DataSourceContextHolder {
// 采用ThreadLocal 保存本地多数据源
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); // 设置数据源类型
public static void setDbType(String dbType) {
contextHolder.set(dbType);
} public static String getDbType() {
return contextHolder.get();
} public static void clearDbType() {
contextHolder.remove();
} }
配置多个数据源:
import javax.sql.DataSource; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*
* 配置多个数据源
*/ @Configuration
public class DataSourceConfig { // 创建可读数据源
@Bean(name = "selectDataSource")
@ConfigurationProperties(prefix = "spring.datasource.select") // application.properteis中对应属性的前缀
public DataSource dataSource1() {
return DataSourceBuilder.create().build();
} // 创建可写数据源
@Bean(name = "updateDataSource")
@ConfigurationProperties(prefix = "spring.datasource.update") // application.properteis中对应属性的前缀
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
} }
将数据源注册到RoutingDataSource中
import java.util.HashMap;
import java.util.Map; import javax.sql.DataSource; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Component; @Component
@Primary
public class DynamicDataSource extends AbstractRoutingDataSource {
@Autowired
@Qualifier("selectDataSource") //获取读的数据源
private DataSource selectDataSource; @Autowired
@Qualifier("updateDataSource") //获取写的数据源
private DataSource updateDataSource; /**
* 这个是主要的方法,返回的是生效的数据源名称
*/
@Override
protected Object determineCurrentLookupKey() {
System.out.println("DataSourceContextHolder:::" + DataSourceContextHolder.getDbType());
return DataSourceContextHolder.getDbType();
} /**
* 配置数据源信息 注册数据源的操作 最终注入到datasource数据源中
*/
@Override
public void afterPropertiesSet() {
Map<Object, Object> map = new HashMap<>();
map.put("selectDataSource", selectDataSource);
map.put("updateDataSource", updateDataSource);
setTargetDataSources(map);
setDefaultTargetDataSource(updateDataSource);
super.afterPropertiesSet();
}
}
然后对于AOP的编写配置:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; import com.mayikt.config.DataSourceContextHolder; @Aspect
@Component
@Lazy(false)
@Order(0) // Order设定AOP执行顺序 使之在数据库事务上先执行 动态数据源事务先执行的
public class SwitchDataSourceAOP {
// 这里切到你的方法目录
@Before("execution(* com.toov5.service.*.*(..))") //扫包范围是业务逻辑层
public void process(JoinPoint joinPoint) {
String methodName = joinPoint.getSignature().getName(); //通过反射获取到方法名称
if (methodName.startsWith("get") || methodName.startsWith("count") || methodName.startsWith("find")
|| methodName.startsWith("list") || methodName.startsWith("select") || methodName.startsWith("check")) {
// 读
DataSourceContextHolder.setDbType("selectDataSource");
} else {
// 切换dataSource
DataSourceContextHolder.setDbType("updateDataSource");
}
}
}
启动:
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
@MapperScan(basePackages = "com.toov5.mapper")
public class AppMybatis { public static void main(String[] args) {
SpringApplication.run(AppMybatis.class, args);
} }
yml:
spring:
datasource:
###可读数据源
select:
jdbc-url: jdbc:mysql://192.168.91.7:8066/mycat_testdb
driver-class-name: com.mysql.jdbc.Driver
username: user
password: user
####可写数据源
update:
jdbc-url: jdbc:mysql://192.168.91.7:8066/mycat_testdb
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
type: com.alibaba.druid.pool.DruidDataSource
注意数据源的配置:是MyCat的域名和端口
Controller:
import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import com.mayikt.entity.UserEntity;
import com.mayikt.service.UserService; @RestController
public class UserController { @Autowired
private UserService userService; @RequestMapping("/findUser")
public List<UserEntity> findUser() {
return userService.findUser();
} @RequestMapping("/insertUser")
public List<UserEntity> insertUser(String userName) {
return userService.insertUser(userName);
} }
entity:
public class UserEntity {
    private String userName;
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}
service:
import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.mayikt.entity.UserEntity;
import com.mayikt.mapper.UserMapper; @Service
public class UserService {
@Autowired
private UserMapper userMapper; public List<UserEntity> findUser() {
return userMapper.findUser();
} public List<UserEntity> insertUser(String userName) {
return userMapper.insertUser(userName);
} }
mapper:
import java.util.List; import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select; import com.mayikt.entity.UserEntity; public interface UserMapper {
@Select("SELECT * FROM user_info ")
public List<UserEntity> findUser(); @Select("insert into user_info values (null,#{userName}); ")
public List<UserEntity> insertUser(@Param("userName") String userName);
}
SpringBoot和Mycat动态数据源项目整合的更多相关文章
- SpringBoot+Mybatis 实现动态数据源切换方案
		背景 最近让我做一个大数据的系统,分析了一下,麻烦的地方就是多数据源切换抽取数据.考虑到可以跨服务器跨数据库抽数,再整理数据,就配置了这个动态数据源的解决方案.在此分享给大家. 实现方案 数据库配置文 ... 
- 记springboot + MP +Hikari动态数据源配置
		环境准备: springboot 2.1.6 mybatis-plus 数据库驱动 boot 自带hikari驱动 步骤1: 导入多数据源启动工具类 <!-- 多数据源支持 -->< ... 
- SpringBoot(十一)-- 动态数据源
		SpringBoot中使用动态数据源可以实现分布式中的分库技术,比如查询用户 就在用户库中查询,查询订单 就在订单库中查询. 一.配置文件application.properties # 默认数据源 ... 
- SpringBoot整合MyBatisPlus配置动态数据源
		目录 SpringBoot整合MyBatisPlus配置动态数据源 SpringBoot整合MyBatisPlus配置动态数据源 推文:2018开源中国最受欢迎的中国软件MyBatis-Plus My ... 
- springboot+shiro+redis(单机redis版)整合教程-续(添加动态角色权限控制)
		相关教程: 1. springboot+shiro整合教程 2. springboot+shiro+redis(单机redis版)整合教程 3. springboot+shiro+redis(集群re ... 
- springboot+mybatis实现动态切换数据源
		前几天有个需求,需要使用不同的数据源,例如某业务要用A数据源,另一个业务要用B数据源.我上网收集了一些资料整合了一下,虽然最后这个需求不了了之了,但是多数据源动态切换还是蛮好用的,所以记录一下,或许以 ... 
- SpringBoot集成Mybatis配置动态数据源
		很多人在项目里边都会用到多个数据源,下面记录一次SpringBoot集成Mybatis配置多数据源的过程. pom.xml <?xml version="1.0" encod ... 
- SpringBoot框架:通过AOP和自定义注解完成druid连接池的动态数据源切换(三)
		一.引入依赖 引入数据库连接池的依赖--druid和面向切面编程的依赖--aop,如下所示: <!-- druid --> <dependency> <groupId&g ... 
- 170714、springboot编程之多数据源切换(动态)
		(1)新建maven java project; 新建一个maven project,取名为:spring-boot-multi-ds (2)在pom.xml添加依赖包: 在pom.xml文件中加入依 ... 
随机推荐
- 查找xcode6的沙盒地目录
			开/查找xcode6的沙盒地目录 用以下代码 打开沙盒目录 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirec ... 
- 你的项目应当使用Spring Boot吗?(译文)
			注:这是一篇译文,参考链接:https://www.e4developer.com/2018/09/24/should-you-use-spring-boot-in-your-project/ Spr ... 
- ios开源东西
			今天,我们将介绍20个在GitHub上非常受开发者欢迎的iOS开源项目,你准备好了吗? 1. AFNetworking 在众多iOS开源项目中,AFNetworking可以称得上是最受开发者欢迎的库项 ... 
- pro-select-limit-if
			drop procedure if exists p9; CREATE PROCEDURE p9 () BEGIN DECLARE a INT; DECLARE b INT; DECLARE c IN ... 
- 如何基于Go搭建一个大数据平台
			如何基于Go搭建一个大数据平台 - Go中国 - CSDN博客 https://blog.csdn.net/ra681t58cjxsgckj31/article/details/78333775 01 ... 
- Spring Mvc4 新特性(一)
			前言 Spring Framework的Web层,由spring-web,spring-webmvc,spring-websocket和spring-webmvc-portlet模块组成. 很多人刚学 ... 
- lombok插件使用
			1.1 lombok介绍 lombok 是一个可以帮助我们简化java代码编写的工具类,尤其是简化javabean的编写,可以通过采用注解的方式,消除代码中的构造方法,getter/setter等代码 ... 
- vue-router 中 meta的用法
			vue-router中的meta,也就是类似于面包屑的功能 路由 代码 用这个获取 嗯,就酱~~ 参考链接:https://blog.csdn.net/qq_32963841/article/deta ... 
- django博客项目8:文章详情页
			首页展示的是所有文章的列表,当用户看到感兴趣的文章时,他点击文章的标题或者继续阅读的按钮,应该跳转到文章的详情页面来阅读文章的详细内容.现在让我们来开发博客的详情页面,有了前面的基础,开发流程都是一样 ... 
- DRF(3) - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件
			一.序列化组件 基于上篇随笔的表结构,通过序列化组件的ModelSerializer设计如下三个接口: GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} PU ... 
