首页 > 作文

SpringBoot 自定义+动态切换数据源教程

更新时间:2023-04-03 23:40:36 阅读: 评论:0

目录
1、添加maven依赖2、配置application.yml3、配置动态数据源4、配置数据源操作holder5、读取自定义数据源,并配置6、动态切换关键——aop进行切换7、使用1)、配置mapper2)、配置rvice3)、单元测试调用4)、测试结果

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?uunicode=true&characterencoding=utf-8    urname: root    password: root    # 下面为连接池的补充设置,应用到上面所有数据源中    # 初始化大小,最小,最大    initialsize: 5    minidle: 5    maxactive: 20    # 配置获取连接等待超时的时间    maxwait: 60000    # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒    timebetweenevictionrunsmillis: 60000    # 配置一个连接在池中最小生存的时间,单位是毫秒    minevictableidletimemillis: 300000    validationquery: lect 1 from dual    testwhileidle: t家长对孩子评语rue    testonborrow: fal    testonreturn: fal    # 打开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?uunicode=true&characterencoding=utf-8      urname: root      password: root    dao:      driver-class-name: com.mysql.jdbc.driver      url: jdbc:mysql://192.168.1.113:3306/test2?uunicode=true&characterencoding=utf-8      urname: root      password: root

3、配置动态数据源

import org.springframework.jdbc.datasource.lookup.abstractroutingdatasource;/** * 动态数据源 * @author 陈梓平 * @date 2017/10/9. */public class dynamicdatasource extends abstractroutingdatasource {    @override    protected object determinecurrentlookupkey() {        return datasourceholder.getdatasource英文优美的句子();    }}

4、配置数据源操作holder

import java.util.arraylist;import java.util.list;/** * 数据源操作 * @author 陈梓平 * @date 2017/10/9. */public class datasourceholder {    //线程本地环境    private static final threadlocal<string> contextholders = new threadlocal<string>();    //数据源列表    public static list<string> datasourceids = new arraylist<>();    //设置数据源    public static void tdatasource(string customertype) {        contextholders.t(customertype);    }    //获取数据源    public static string getdatasource() {        return (string) contextholders.get();    }    //清除数据源    public static void cleardatasource() {        contextholders.remove();    }    /**     * 判断指定datasrouce当前是否存在     * @param datasourceid     * @return     * @author shanhy     * @create  2016年1月24日     */    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.conversionrvice;import org.springframework.core.convert.support.defaultconversionrvice;import org.springframework.core.env.environment;import org.springframework.stereotype.component;import javax.sql.datasource;import java.util.hashmap;import java.util.map;/** * 数据源配置 * @author 陈梓平 * @date 2017/10/9. */@component@configurationpublic class dyna动物分类micdatasourceconfig 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 conversionrvice conversionrvice = new defaultconversionrvice();    private map<string, datasource> customdatasources = new hashmap<>();    @override    public void tenvironment(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("urname", propertyresolver.getproperty("urname"));        dsmap.put("password", propertyresolver.getproperty("password"));        defaultdatasource = builddatasource(dsmap);        datasourceholder.datasourceids.add("ds1");        databinder(defaultdatasource, environment);    }    /**     * 创建datasource     * @param dsmap     * @return     * @author shanhy     * @create 2016年1月24日     */    @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 urname = dsmap.get("urname").tostring();            string password = dsmap.get("password").tostring();            datasourcebuilder factory = datasourcebuilder.create().driverclassname(driverclassname).url(url)                    .urname(urname).password(password).type(datasourcetype);            return factory.build();        } catch (classnotfoundexception e) {            e.printstacktrace();        }        return null;    }    /**     * 为datasource绑定更多数据     * @param datasource     * @param env     * @author shanhy     * @create  2016年1月25日     */    private void databinder(datasource datasource, environment env){        relaxeddatabinder databinder = new relaxeddatabinder(datasource);        //databinder.tvalidator(new localvalidatorfactory().run(this.applicationcontext));        databinder.tconversionrvice(conversionrvice);        databinder.tignorenestedproperties(fal);//fal        databinder.tignoreinvalidfields(fal);//fal        databinder.tignoreunknownfields(true);//true        if(datasourcepropertyvalues == null){            map<string, object> rpr = new relaxedpropertyresolver(env, "druid.d共青团宣誓词atasource.").getsubproperties(".");            map<string, object> values = new hashmap<>(rpr);            // 排除已经设置的属性            values.r月的作文emove("type");            values.remove("driver-class-name");            values.remove("url");            values.remove("urname");            values.remove("password");            datasourcepropertyvalues = new mutablepropertyvalues(values);        }        databinder.bind(datasourcepropertyvalues);    }    @bean(name = "datasource")    public dynamicdatasource datasource() {        dynamicdatasource dynamicdatasource = new dynamicdatasource();        // 默认数据源        dynamicdatasource.tdefaulttargetdatasource(defaultdatasource);        // 配置多数据源        map<object, object> dsmap = new hashmap(5);        dsmap.put("ds1", defaultdatasource);        dsmap.putall(customdatasources);        for (string key : customdatasources.keyt())            datasourceholder.datasourceids.add(key);        dynamicdatasource.ttargetdatasources(dsmap);        return dynamicdatasource;    }}

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

/** * 动态数据源注解 * @author 陈梓平 * @date 2017/10/9. */@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;/** * 设置数据源切面 * @author 陈梓平 * @date 2017/10/9. */@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());        } el {            logger.debug("u datasource : {} > {}", ds.name(), point.getsignature());            datasourceholder.tdatasource(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

/** * @author 陈梓平 * @date 2017/10/9. */public interface dynamicdsmapper {    integer queryjournal();    string queryur();    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">    <lect id="queryjournal" resulttype="java.lang.integer">        lect uid from journal    </lect>    <lect id="queryur" resulttype="java.lang.string">        lect name from ur    </lect>    <lect id="querytype" resulttype="java.lang.string">        lect parent from p_type    </lect></mapper>

2)、配置rvice

/** * @author 陈梓平 * @date 2017/10/9. */@rvicepublic class dynamicrvciceimpl implements dynamicrvcice {    @autowired    private dynamicdsmapper dynamicdsmapper;    @ds()    public integer ds1() {        return dynamicdsmapper.queryjournal();    }    @ds(name = "logic")    public string ds2() {        return dynamicdsmapper.queryur();    }    @ds(name = "dao")    public string ds3() {        return dynamicdsmapper.querytype();    }}

3)、单元测试调用

/** * 多数原测试 * @author 陈梓平 * @date 2017/10/9. */@runwith(springrunner.class)@springboottestpublic class testdynamicds {    private logger logger = loggerfactory.getlogger(testdynamicds.class);//    @autowired    private dynamicrvcice dynamicrvcice;    @test    public void test() {//        integer integer = dynamicrvcice.ds1();//        logger.info("integer:"+integer);//        string ds2 = dynamicrvcice.ds2();//        logger.info("ds2:"+ds2);        string ds3 = dynamicrvcice.ds3();        logger.info("ds3:"+ds3);    }}

4)、测试结果

以上为个人经验,希望能给大家一个参考,也希望大家多多支持www.887551.com。

本文发布于:2023-04-03 23:40:33,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/f9f650abbe30e52e64fde93d68a5c61c.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:SpringBoot 自定义+动态切换数据源教程.doc

本文 PDF 下载地址:SpringBoot 自定义+动态切换数据源教程.pdf

标签:数据源   动态   多个   属性
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图