iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >SpringBoot自定义动态切换数据源的方法是什么
  • 756
分享到

SpringBoot自定义动态切换数据源的方法是什么

2023-06-21 22:06:45 756人浏览 泡泡鱼
摘要

本篇内容主要讲解“SpringBoot自定义动态切换数据源的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“springBoot自定义动态切换数据源的方法是什么”吧!1、添加Maven依

本篇内容主要讲解“SpringBoot自定义动态切换数据源的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习springBoot自定义动态切换数据源的方法是什么”吧!

1、添加Maven依赖

<dependency>            <groupId>mysql</groupId>            <artifactId>Mysql-connector-java</artifactId>            <scope>runtime</scope>        </dependency>        <dependency>            <groupId>com.alibaba</groupId>            <artifactId>druid</artifactId>            <version>1.1.3</version>        </dependency>        <!--properties动态注入-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-configuration-processor</artifactId>            <optional>true</optional>        </dependency>        <!--springBoot的aop-->        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-aop</artifactId>        </dependency>

2、配置application.yml

数据库访问配置# 主数据源,默认的druid:  datasource:    type: com.alibaba.druid.pool.DruidDataSource    driver-class-name: com.mysql.jdbc.Driver    url: jdbc:mysql://192.168.1.113:3306/test?useUnicode=true&characterEncoding=utf-8    username: root    passWord: root    # 下面为连接池的补充设置,应用到上面所有数据源中    # 初始化大小,最小,最大    initialSize: 5    minIdle: 5    maxActive: 20    # 配置获取连接等待超时的时间    maxWait: 60000    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒    timeBetweenEvictionRunsMillis: 60000    # 配置一个连接在池中最小生存的时间,单位是毫秒    minEvictableIdleTimeMillis: 300000    validationQuery: SELECT 1 FROM DUAL    testWhileIdle: true    testOnBorrow: false    testOnReturn: false    # 打开PSCache,并且指定每个连接上PSCache的大小    poolPreparedStatements: true    maxPoolPreparedStatementPerConnectionSize: 20    # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙    filters: stat,wall,log4j    # 通过connectProperties属性来打开mergeSql功能;慢SQL记录    connectionProperties:      druid:        stat:          mergeSql: true          slowSqlMillis: 5000    # 合并多个DruidDataSource的监控数据#多数据源mysql-db:  datasource:    names: logic,dao    logic:      driver-class-name: com.mysql.jdbc.Driver      url: jdbc:mysql://192.168.1.113:3306/test1?useUnicode=true&characterEncoding=utf-8      username: root      password: root    dao:      driver-class-name: com.mysql.jdbc.Driver      url: jdbc:mysql://192.168.1.113:3306/test2?useUnicode=true&characterEncoding=utf-8      username: root      password: root

3、配置动态数据源

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class DynamicDataSource extends AbstractRoutingDataSource {    @Override    protected Object determineCurrentLookupKey() {        return DataSourceHolder.getDataSource();    }}

4、配置数据源操作Holder

import java.util.ArrayList;import java.util.List;public class DataSourceHolder {    //线程本地环境    private static final ThreadLocal<String> contextHolders = new ThreadLocal<String>();    //数据源列表    public static List<String> dataSourceIds = new ArrayList<>();    //设置数据源    public static void setDataSource(String customerType) {        contextHolders.set(customerType);    }    //获取数据源    public static String getDataSource() {        return (String) contextHolders.get();    }    //清除数据源    public static void clearDataSource() {        contextHolders.remove();    }        public static boolean containsDataSource(String dataSourceId){        return dataSourceIds.contains(dataSourceId);    }}

5、读取自定义数据源,并配置

import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.MutablePropertyValues;import org.springframework.beans.PropertyValues;import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;import org.springframework.boot.bind.RelaxedDataBinder;import org.springframework.boot.bind.RelaxedPropertyResolver;import org.springframework.context.EnvironmentAware;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.convert.ConversionService;import org.springframework.core.convert.support.DefaultConversionService;import org.springframework.core.env.Environment;import org.springframework.stereotype.Component;import javax.sql.DataSource;import java.util.HashMap;import java.util.Map;@Component@Configurationpublic class DynamicDataSourceConfig implements EnvironmentAware {    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceConfig.class);    // 默认数据源    private DataSource defaultDataSource;    // 属性值    private PropertyValues dataSourcePropertyValues;    // 如配置文件中未指定数据源类型,使用该默认值    private static final Object DATASOURCE_TYPE_DEFAULT = "org.apache.Tomcat.jdbc.pool.DataSource";    private ConversionService conversionService = new DefaultConversionService();    private Map<String, DataSource> customDataSources = new HashMap<>();    @Override    public void setEnvironment(Environment environment) {        initDefaultDatasource(environment);        initOtherDatasource(environment);    }    private void initOtherDatasource(Environment environment) {        RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "mysql-db.datasource.");        String dsPrefixs = propertyResolver.getProperty("names");        for (String dsPrefix : dsPrefixs.split(",")) {// 多个数据源            Map<String, Object> dsMap = propertyResolver.getSubProperties(dsPrefix+".");            DataSource ds = buildDataSource(dsMap);            customDataSources.put(dsPrefix, ds);            dataBinder(ds, environment);        }    }    private void initDefaultDatasource(Environment environment) {        // 读取主数据源        RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(environment, "druid.datasource.");        Map<String, Object> dsMap = new HashMap<>();        dsMap.put("type", propertyResolver.getProperty("type"));        dsMap.put("driver-class-name", propertyResolver.getProperty("driver-class-name"));        dsMap.put("url", propertyResolver.getProperty("url"));        dsMap.put("username", propertyResolver.getProperty("username"));        dsMap.put("password", propertyResolver.getProperty("password"));        defaultDataSource = buildDataSource(dsMap);        DataSourceHolder.dataSourceIds.add("ds1");        dataBinder(defaultDataSource, environment);    }        @SuppressWarnings("unchecked")    public DataSource buildDataSource(Map<String, Object> dsMap) {        try {            Object type = dsMap.get("type");            if (type == null)                type = DATASOURCE_TYPE_DEFAULT;// 默认DataSource            Class<? extends DataSource> dataSourceType;            dataSourceType = (Class<? extends DataSource>) Class.forName((String) type);            String driverClassName = dsMap.get("driver-class-name").toString();            String url = dsMap.get("url").toString();            String username = dsMap.get("username").toString();            String password = dsMap.get("password").toString();            DataSourceBuilder factory = DataSourceBuilder.create().driverClassName(driverClassName).url(url)                    .username(username).password(password).type(dataSourceType);            return factory.build();        } catch (ClassNotFoundException e) {            e.printStackTrace();        }        return null;    }        private void dataBinder(DataSource dataSource, Environment env){        RelaxedDataBinder dataBinder = new RelaxedDataBinder(dataSource);        //dataBinder.setValidator(new LocalValidatorFactory().run(this.applicationContext));        dataBinder.setConversionService(conversionService);        dataBinder.setIgnoreNestedProperties(false);//false        dataBinder.setIgnoreInvalidFields(false);//false        dataBinder.setIgnoreUnknownFields(true);//true        if(dataSourcePropertyValues == null){            Map<String, Object> rpr = new RelaxedPropertyResolver(env, "druid.datasource.").getSubProperties(".");            Map<String, Object> values = new HashMap<>(rpr);            // 排除已经设置的属性            values.remove("type");            values.remove("driver-class-name");            values.remove("url");            values.remove("username");            values.remove("password");            dataSourcePropertyValues = new MutablePropertyValues(values);        }        dataBinder.bind(dataSourcePropertyValues);    }    @Bean(name = "dataSource")    public DynamicDataSource dataSource() {        DynamicDataSource dynamicDataSource = new DynamicDataSource();        // 默认数据源        dynamicDataSource.setDefaultTargetDataSource(defaultDataSource);        // 配置多数据源        Map<Object, Object> dsMap = new HashMap(5);        dsMap.put("ds1", defaultDataSource);        dsMap.putAll(customDataSources);        for (String key : customDataSources.keySet())            DataSourceHolder.dataSourceIds.add(key);        dynamicDataSource.setTargetDataSources(dsMap);        return dynamicDataSource;    }}

6、动态切换关键——AOP进行切换

@Retention(RetentionPolicy.RUNTIME)@Target({        ElementType.METHOD})public @interface DS {    String name() default "ds1";}
import com.chen.config.dynamicDS.DataSourceHolder;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.After;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;@Aspect@Order(-1)// 保证该AOP在@Transactional之前执行@Componentpublic class DynamicDataSourceAspect {    private static final Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);    @Before("@annotation(ds)")    public void changeDataSource(JoinPoint point, DS ds) throws Throwable {        String dsId = ds.name();        if (!DataSourceHolder.containsDataSource(dsId)) {            logger.error("数据源[{}]不存在,使用默认数据源 > {}", ds.name(), point.getSignature());        } else {            logger.debug("Use DataSource : {} > {}", ds.name(), point.getSignature());            DataSourceHolder.setDataSource(ds.name());        }    }    @After("@annotation(ds)")    public void restoreDataSource(JoinPoint point, DS ds) {        logger.debug("Revert DataSource : {} > {}", ds.name(), point.getSignature());        DataSourceHolder.clearDataSource();    }}

7、使用

1)、配置mapper

public interface DynamicDSMapper {    Integer queryJournal();    String queryUser();    String queryType();}
<?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.chen.mapper.DynamicDSMapper">    <select id="queryJournal" resultType="java.lang.Integer">        SELECT uid FROM journal    </select>    <select id="queryUser" resultType="java.lang.String">        SELECT name FROM user    </select>    <select id="queryType" resultType="java.lang.String">        SELECT parent FROM p_type    </select></mapper>

2)、配置service

@Servicepublic class DynamicServciceImpl implements DynamicServcice {    @Autowired    private DynamicDSMapper dynamicDSMapper;    @DS()    public Integer ds1() {        return dynamicDSMapper.queryJournal();    }    @DS(name = "logic")    public String ds2() {        return dynamicDSMapper.queryUser();    }    @DS(name = "dao")    public String ds3() {        return dynamicDSMapper.queryType();    }}

3)、单元测试调用

@RunWith(SpringRunner.class)@SpringBootTestpublic class TestDynamicDS {    private Logger logger = LoggerFactory.getLogger(TestDynamicDS.class);//    @Autowired    private DynamicServcice dynamicServcice;    @Test    public void test() {//        Integer integer = dynamicServcice.ds1();//        logger.info("integer:"+integer);//        String ds2 = dynamicServcice.ds2();//        logger.info("ds2:"+ds2);        String ds3 = dynamicServcice.ds3();        logger.info("ds3:"+ds3);    }}

4)、测试结果

SpringBoot自定义动态切换数据源的方法是什么

到此,相信大家对“SpringBoot自定义动态切换数据源的方法是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: SpringBoot自定义动态切换数据源的方法是什么

本文链接: https://www.lsjlt.com/news/301055.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • SpringBoot自定义动态切换数据源的方法是什么
    本篇内容主要讲解“SpringBoot自定义动态切换数据源的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot自定义动态切换数据源的方法是什么”吧!1、添加maven依...
    99+
    2023-06-21
  • SpringBoot自定义+动态切换数据源教程
    目录1、添加maven依赖2、配置application.yml3、配置动态数据源4、配置数据源操作Holder5、读取自定义数据源,并配置6、动态切换关键——AOP进行切换7、使用...
    99+
    2022-11-12
  • 详细聊聊SpringBoot中动态切换数据源的方法
    其实这个表示有点不太对,应该是 Druid 动态切换数据源的方法,只是应用在了 springboot 框架中,准备代码准备了半天,之前在一次数据库迁移中使用了,发现 Druid 还是...
    99+
    2022-11-12
  • 【mybatis-plus】自定义多数据源,动态切换数据源事务失效问题
    背景 做了一个和navicat一样的工具,web版工具,然后数据库链接信息都是存在一个主数据库表的里,所以这里涉及到了动态切换数据源,以及一些事务等。今天说下多数据源切换时,事务失效。 目录  一、常见的事务失效 @Transac...
    99+
    2023-09-08
    mybatis 数据库 mysql
  • spring-data-redis 动态切换数据源的方法
    最近遇到了一个麻烦的需求,我们需要一个微服务应用同时访问两个不同的 Redis 集群。一般我们不会这么使用 Redis,但是这两个 Redis 本来是不同业务集群,现在需要一个微服...
    99+
    2022-11-12
  • 基于mybatis plus实现数据源动态添加、删除、切换,自定义数据源的示例代码
    目录简介代码示例mavne依赖数据源增加、移除数据源切换基于AOP切换基于重写处理器自定义数据源简介 基于springboot,mybatis plus集成了一套多数据源的解决方案,...
    99+
    2022-11-13
  • SpringBoot数据访问自定义使用Druid数据源的方法
    数据访问之Druid数据源的使用 说明:该数据源Druid,使用自定义方式实现,后面文章使用start启动器实现,学习思路为主。 为什么要使用数据源: ​数据源是提高数...
    99+
    2022-11-12
  • vue自定义动态组件的方法是什么
    本篇内容主要讲解“vue自定义动态组件的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“vue自定义动态组件的方法是什么”吧! Vue.extend 思路就是拿到组件...
    99+
    2023-07-04
  • java动态数组定义的方法是什么
    在Java中,可以使用以下两种方法定义动态数组:1. 使用ArrayList类:ArrayList是Java中提供的一个动态数组类,...
    99+
    2023-10-20
    java
  • java自定义切面增强的方法是什么
    本篇内容主要讲解“java自定义切面增强的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“java自定义切面增强的方法是什么”吧!java自定义切面增强1. 自定义一个注解@Target...
    99+
    2023-07-05
  • mysql自定义函数的方法是什么
    在MySQL中,可以使用以下步骤来创建自定义函数:1. 创建函数:使用`CREATE FUNCTION`语句来创建函数,并指定函数的...
    99+
    2023-09-11
    mysql
  • Spring Cloud自定义引导属性源的方法是什么
    本篇内容介绍了“Spring Cloud自定义引导属性源的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!引导过程添加的外部配置的默...
    99+
    2023-06-05
  • SpringBoot多数据源读写分离的自定义配置问题及解决方法
    目录针对device库我们先创建一个数据库连接配置类在类中添加配置文件中的读写数据源创建返回SqlSessionFactory的Bean创建SqlSessionTemplate的Be...
    99+
    2022-11-13
  • Springboot项目启动时动态指定环境的方法是什么
    本篇内容介绍了“Springboot项目启动时动态指定环境的方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Springboot 启...
    99+
    2023-07-06
  • Springboot自带定时任务实现动态配置Cron参数方式是是什么
    这篇文章主要讲解了“Springboot自带定时任务实现动态配置Cron参数方式是是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Springboot自带定时任务实现动态配置Cron参数...
    99+
    2023-06-25
  • Python catplot函数自定义颜色的方法是什么
    一、catplot函数catplot() 函数是 Seaborn 中一个非常有用的函数,它可以绘制分类变量的图形,并可以根据另一个或多个变量进行分组。使用不同的图表类型,catplot() 函数可以创建适当的图表。默认情况下,catplot...
    99+
    2023-05-18
    Python
  • SpringBoot整合sharding-jdbc实现自定义分库分表的方法是什么
    这篇文章主要讲解了“SpringBoot整合sharding-jdbc实现自定义分库分表的方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringBoot整合sharding-j...
    99+
    2023-06-25
  • SpringBoot整合Mybatis Plus多数据源的实现方法是什么
    这篇文章主要讲解了“SpringBoot整合Mybatis Plus多数据源的实现方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“SpringBoot整合Mybatis Plus多数...
    99+
    2023-06-25
  • 微信小程序自定义函数的方法是什么
    在微信小程序中,可以通过以下方法自定义函数:1. 在`app.js`中定义全局函数:可以在`App`函数中定义全局函数,这样在整个小...
    99+
    2023-09-29
    微信小程序
  • listview自动刷新数据的方法是什么
    ListView自动刷新数据有多种方法,以下是其中的几种常用方法:1. 使用Handler和Runnable:在主线程中使用Hand...
    99+
    2023-09-14
    listview
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作