为什么80%的码农都做不了架构师?>>>   

序言:这个读写分离摘自于Springboot多数据源快速启动器,读写分离的话并不是按照传统方式的springmvc看方法命名那样,而是在每个方法上加注解或者类上添加注解表明选用的数据源。支持事物!

1、创建Springboot项目

勾选Web,Mysql,MyBatis三个模块,最终创建springboot项目成功

2、pom.xml 添加属性依赖

<!-- springboot-aop包,AOP切面注解,Aspectd等相关注解 -->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

3、添加application.properties 属性配置

server.port=8088
#数据源1
spring.datasource.db1.jdbc-url=jdbc:mysql://127.0.0.1:3306/test_msg2?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.db1.username=root
spring.datasource.db1.password=root
spring.datasource.db1.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.db1.max-idle=10
spring.datasource.db1.max-wait=10000
spring.datasource.db1.min-idle=5
spring.datasource.db1.initial-size=5
#数据源2
spring.datasource.db2.jdbc-url=jdbc:mysql://127.0.0.1:3306/test_msg3?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.db2.username=root
spring.datasource.db2.password=root
spring.datasource.db2.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.db2.max-idle=10
spring.datasource.db2.max-wait=10000
spring.datasource.db2.min-idle=5
spring.datasource.db2.initial-size=5
#mybatis
mybatis.mapper-locations=classpath*:mapper/*.xml
mybatis.type-aliases-package=com.springboot2.mjt04.dao

4、编写代码

4.0 实体类

public class User {private int id;private String name;private int age;public User(){}public User(String name, int age){this.name = name;this.age  = age;}public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

4.1 创建UserDao.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" ><mapper namespace="com.springboot2.mjt04.dao.UserDao"><!-- 查询所有user --><select id="getAllUser" resultType="java.util.Map">select * from user</select><!-- 添加数据并返回主键ID,接收主键,必须以实体类接收 --><!-- keyColumn="id"对应数据库字段,keyProperty="id"对应实体类属性  --><insert id="addUserGetID" parameterType="com.springboot2.mjt04.entity.User" useGeneratedKeys="true" keyColumn="id" keyProperty="id">insert into user(name,age) values(#{name},#{age})</insert><insert id="addUser">insert into user(name,age) values(#{name},#{age})</insert>
</mapper>

4.2 UserDao

@Mapper
public interface UserDao {//使用xml配置形式查询List<Map> getAllUser();Long addUserGetID(User user);void addUser(User user);
}

4.3 UserService

@Service
public class UserService {@Autowiredprivate UserDao moredataDao;//使用数据源1查询@DS("datasource1")public List<Map> getAllUser1(){return moredataDao.getAllUser();}//使用数据源2查询@DS("datasource2")public List<Map> getAllUser2(){return moredataDao.getAllUser();}//使用数据源1插入数据@DS("datasource1")public Long addUserGetID1(User user){return moredataDao.addUserGetID(user);}//使用数据源1插入数据@DS("datasource2")public Long addUserGetID2(User user){return moredataDao.addUserGetID(user);}//使用数据源1插入数据@DS("datasource1")public void addUser1(User user){moredataDao.addUser(user);}//使用数据源2插入数据@DS("datasource2")public void addUser2(User user){moredataDao.addUser(user);}@Transactionalpublic void test1(){moredataDao.addUserGetID(new User("mdx1",18));int a =10/0;moredataDao.addUserGetID(new User("mdxl1",20));}}

4.4 创建controller

@Controller
public class RWController {@AutowiredUserService userService;//走数据源1库@GetMapping(value = "/test1")@ResponseBodypublic String testOne(){User user = new User("mjt01",20);userService.addUser1(user);return "success";}//使用数据源2插入数据@GetMapping(value = "/test2")@ResponseBodypublic String testTwo(){User user = new User("mjt02",20);userService.addUser2(user);return "success";}}

4.5 添加mysql多数据源配置文件类

5个配置文件,切记如果照着写的话,小心里面的路径要准确对应上

//import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
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;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;/*** 多数据源配置类* Created by pure on 2018-05-06.*/
@Configuration
public class DataSourceConfig {//数据源1@Bean(name = "datasource1")@ConfigurationProperties(prefix = "spring.datasource.db1") // application.properteis中对应属性的前缀public DataSource dataSource1() {return DataSourceBuilder.create().build();}//数据源2@Bean(name = "datasource2")@ConfigurationProperties(prefix = "spring.datasource.db2") // application.properteis中对应属性的前缀public DataSource dataSource2() {return DataSourceBuilder.create().build();}/*** 动态数据源: 通过AOP在不同数据源之间动态切换* @return*/@Primary@Bean(name = "dynamicDataSource")public DataSource dynamicDataSource() {DynamicDataSource dynamicDataSource = new DynamicDataSource();// 默认数据源dynamicDataSource.setDefaultTargetDataSource(dataSource1());// 配置多数据源Map<Object, Object> dsMap = new HashMap();dsMap.put("datasource1", dataSource1());dsMap.put("datasource2", dataSource2());dynamicDataSource.setTargetDataSources(dsMap);return dynamicDataSource;}/*** 配置@Transactional注解事物* @return*/@Beanpublic PlatformTransactionManager transactionManager() {return new DataSourceTransactionManager(dynamicDataSource());}
}
public class DataSourceContextHolder {/*** 默认数据源*/public static final String DEFAULT_DS = "datasource1";private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();// 设置数据源名public static void setDB(String dbType) {System.out.println("切换到{"+dbType+"}数据源");contextHolder.set(dbType);}// 获取数据源名public static String getDB() {return (contextHolder.get());}// 清除数据源名public static void clearDB() {contextHolder.remove();}
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface DS {String value() default "datasource1";
}
public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {System.out.println("数据源为"+DataSourceContextHolder.getDB());return DataSourceContextHolder.getDB();}
}
@Aspect
@Component
public class DynamicDataSourceAspect {@Before("@annotation(com.springboot2.mjt04.config.mysql.DS)")public void beforeSwitchDS(JoinPoint point){//获得当前访问的classClass<?> className = point.getTarget().getClass();//获得访问的方法名String methodName = point.getSignature().getName();//得到方法的参数的类型Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();String dataSource = DataSourceContextHolder.DEFAULT_DS;try {// 得到访问的方法对象Method method = className.getMethod(methodName, argClass);// 判断是否存在@DS注解if (method.isAnnotationPresent(DS.class)) {DS annotation = method.getAnnotation(DS.class);// 取出注解中的数据源名dataSource = annotation.value();}} catch (Exception e) {e.printStackTrace();}// 切换数据源DataSourceContextHolder.setDB(dataSource);}@After("@annotation(com.springboot2.mjt04.config.mysql.DS)")public void afterSwitchDS(JoinPoint point){DataSourceContextHolder.clearDB();}
}

最终目录结构图:

5、注意的问题:

5.1 出现这个错误 jdbcUrl is required with driverClassName.运行出现这个过程是因为在多数据源的情况下,springboot2.0与1.X版本都不同配置属性,解决jdbcUrl is required with driverClassName.问题,点击这里,但是我现在已经改过来了,以前是

spring.datasource.db1.url=jdbc:mysql://127.0.0.1:3306/test_msg2?useUnicode=true&characterEncoding=utf-8&useSSL=false

而现在添加了jdbc-url

spring.datasource.db1.jdbc-url=jdbc:mysql://127.0.0.1:3306/test_msg2?useUnicode=true&characterEncoding=utf-8&useSSL=false

5.2 包名路径跟换

以前1.X版本为

import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;

而现在2.X版本

import org.springframework.boot.jdbc.DataSourceBuilder;

注意一下就好,因为我都给大家改好了。

5.3 事物可以正常使用,也支持读写分离,不过在事物的方法可能比springmvc的项目麻烦些,毕竟目前我的技术只能用注解才能切换数据源,目前我没有成功找到在配置类根据方法前缀名就可以判断数据源的。

5.4

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

这个是application启动类上面的一个注解,表明是不使用DataSourceAutoCOnfiguration.class,因为我们的是多个数据源,不能默认使用一个单数据源,所以要加上这个。

成功!不懂可以私信我或者留言就好。

转载于:https://my.oschina.net/mdxlcj/blog/1835656

崛起于Springboot2.X之Mysql读写分离(6)相关推荐

  1. proxy实现 mysql 读写分离

    实现 mysql 读写分离 图解: 环境: iptables 和 selinux 关闭 proxy:test2 172.25.1.2 Master: test3 172.25.1.3 Slave:te ...

  2. 项目性能优化(MySQL读写分离、MySQL主从同步、Django实现MySQL读写分离)

    当项目中数据库表越来越多,数据量也逐渐增多时,需要做数据库的安全和性能的优化.对于数据库的优化,可以选择使用MySQL读写分离实现. 1.MySQL主从同步 1.主从同步机制 1.1.主从同步介绍和优 ...

  3. asp.net mysql 读写分离_MySQL读写分离

    MySQL读写分离 1,为啥要读写分离? 系统到了高并发阶段,数据库一定要做的读写分离了,因为大部分的项目都是读多写少.所以针对这个情况,把写操作放一个主库,主库下挂多个从库处理读操作,这样就可以支撑 ...

  4. mysql读写分离,主从配置

    2019独角兽企业重金招聘Python工程师标准>>> 一个完整的mysql读写分离环境包括以下几个部分: 应用程序client database proxy database集群 ...

  5. php mysql读写分离主从复制_mysql主从复制 读写分离原理及实现

    主从复制,读写分离原理 在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足实际需求的.无论是在安全性.高可用性还是高并发等各个方面都是完全不能满足实际需求的.因此,通过主从复制的 ...

  6. centos mysql卸载重装_提高性能,MySQL 读写分离环境搭建

    MySQL 读写分离在互联网项目中应该算是一个非常常见的需求了.受困于 Linux 和 MySQL 版本问题,很多人经常会搭建失败,今天松哥就给大伙举一个成功的例子,后面有时间再和大家分享下使用 Do ...

  7. sae mysql django_Django中MySQL读写分离技术

    最近需要用到Django的MySQL读写分离技术,查了一些资料,把方法整理了下来. 在Django里实现对MySQL的读写分离,实际上就是将不同的读写请求按一定的规则路由到不同的数据库上(可以是不同类 ...

  8. mysql读写分离有用吗_MySQL的使用中实现读写分离的教程

    mysql-proxy实现读写分离 MySQL Proxy是一个处于你的client端和MySQL server端之间的简单程序,它可以监测.分析或改变它们的通信.它使用灵活,没有限制,常见的用途包括 ...

  9. mysql读写分离_Mysql数据库09MySQL读写分离

    Mysql数据库09-MySQL读写分离 一.读写分离应用案例分析 在企业用户中,在大量的数据请求下,单台数据库将无法承担所有读写操作.解决方法:配置多台数据库服务器以实现主从复制+读写分离. 二.读 ...

最新文章

  1. python基础知识练习题
  2. Python能让你上天?带你挖掘隐藏彩蛋~(附代码)
  3. F5 云应用服务促进公共云、私有云及混合云应用部署
  4. ubuntu java sdk_ubuntu 10.10安装java sdk6过程
  5. CodeForces - 103E Buying Sets(最小权闭合子图)
  6. ubuntu设置静态ip
  7. 线程的属性 —— 分离的状态(detached state)、栈地址(stack address)、栈大小(stack size)
  8. Django 博客开发教程 6 - 真正的 Django 博客首页视图
  9. 下载与eclipse匹配的hibernate tools
  10. Altium AD20原理图从库中更新变动,库中模型修改后同步到原理图中
  11. 为什么说即便是新手,也应该学习微服务?
  12. 英语 动词过去式和过去分词的变化规则
  13. 阿里、华为都是外包公司?
  14. inl和dnl matlab_AD的一些指标——INL与DNL
  15. 四川托普计算机职业学校环境,四川四川托普计算机职业学校
  16. 文档印刷体中字符类符号
  17. 动态图解实例 ConstraintLayout Chain
  18. linux中权限设置,Linux 权限设置chmod
  19. 【水位预测】基于matlab径向基神经网络地下水位预测【含Matlab源码 1939期】
  20. 校准不好TOF相机就废了?

热门文章

  1. 凯利公式自动计算表_EXCEL——可自动计算的收支表,全函数计算,拿上就用!
  2. java 日志管理源码_Java源码初探_logging日志模块实现
  3. 云开发无需服务期无需域名壁纸小程序源码
  4. 从wordpress到octopress
  5. __call、__set 和 __get的用法
  6. JavaScript 触发click事件 兼容FireFox,IE 和 Chrome
  7. 轻量级的 JavaScript 弹出框脚本:TinyBox
  8. 剑指offer 26.数字的子结构
  9. 人工智障学习笔记——机器学习(8)K均值聚类
  10. Go 标准库: io