第一步、在nacos中加入

spring:
  datasource:
    master:
      url: jdbc:mysql://base-mysql:3306/XXX?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource
      name: master
      initialize: true
      filters: stat
    slave1:
      url: jdbc:mysql://base-mysql:3306/XXX?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true
      username: root
      password: root
      driver-class-name: com.mysql.cj.jdbc.Driver
      type: com.alibaba.druid.pool.DruidDataSource
      name: slave1
      initialize: true
      filters: stat

其中的的 base-mysql是配置了host 使用ip即可
这样我们就配置好了两个数据源分别为 master和slave1
之后去到spring 启动页面添加

@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})

之后自定义的数据源的注解

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Retention(RetentionPolicy.RUNTIME)
@Target({
        ElementType.METHOD
})
public @interface MyDataSource {
    String value() default "master";
}

操作数据源

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class DynamicDataSourceSwitcher {

    static Logger logger = LoggerFactory.getLogger(DynamicDataSourceSwitcher.class);

    public static final String Mater = "master";
    public static final String Slave1 = "slave1";

    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

    public static void setDataSource(String name){
        logger.info("-------- 设置数据源数据源为 :{} ", name);
        contextHolder.set(name);
    }

    public static String getDataSource(){
            if (StringUtils.isEmpty(CONTEXTHOLDER.get())) {
            setDataSource(MATER);
        }
        return contextHolder.get();
    }

    public static void cleanDataSource(){
        contextHolder.remove();
    }

}

多数据源bean的配置类

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;


import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class MultipleDataSourceConfig {

    @Bean("master")
    @ConfigurationProperties(prefix = "spring.datasource.master")
    public DataSource createMasterDataSource(){
        return new DruidDataSource();
    }

    @Bean("slave1")
    @ConfigurationProperties(prefix = "spring.datasource.slave1")
    public DataSource createSlave1DataSource(){
        return new DruidDataSource();
    }

    /**
     * 设置动态数据源,通过@Primary 来确定主DataSource
     * @return
     */
    @Bean
    @Primary
    public DataSource createDynamicDataSource(@Qualifier("master") DataSource master, @Qualifier("slave1") DataSource slave1){
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        //设置默认数据源
        dynamicDataSource.setDefaultTargetDataSource(master);
        //配置多数据源
        Map<Object, Object> map = new HashMap<>();
        map.put("master",master);
        map.put("slave1",slave1);
        dynamicDataSource.setTargetDataSources(map);
        return  dynamicDataSource;
    }
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;


public class DynamicDataSource extends AbstractRoutingDataSource {

    Logger logger = LoggerFactory.getLogger(DynamicDataSource.class);

    @Override
    protected Object determineCurrentLookupKey() {
        logger.info("------------------当前数据源 {}", DynamicDataSourceSwitcher.getDataSource());
        return DynamicDataSourceSwitcher.getDataSource();
    }
}

创建aop切面

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Order(1)
public class DynamicDataSourceAspect {
    private Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);

    /**
     * 切入点只对@Service注解的类上的@DataSource方法生效
     * @param myDataSource
     */
    @Pointcut(value="@within(org.springframework.stereotype.Service) && @annotation(myDataSource)" )
    public void dynamicDataSourcePointCut(MyDataSource myDataSource){}

    @Before(value = "dynamicDataSourcePointCut(myDataSource)")
    public void switchDataSource(MyDataSource myDataSource) {
        DynamicDataSourceSwitcher.setDataSource(myDataSource.value());
    }

    /**
     * 切点执行完后 切换成主数据库
     * @param myDataSource
     */
    @After(value="dynamicDataSourcePointCut(myDataSource)")
    public void after(MyDataSource myDataSource){
        DynamicDataSourceSwitcher.cleanDataSource();
    }
}

之后在service中使用即可

    @Override
    @MyDataSource(value = DynamicDataSourceSwitcher.Slave1)
    public List<Map> getAllByArticleTitleOne() {
        return articleBodysMapper.getAllByArticleTitleOne();
    }

这样就成功使用的是Slave1的数据库

之后配置监控页面


import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class DruidConfig {
    

    /**
     * 配置Druid的监控:一个管理后台的Servlet
     */
    @Bean
    public ServletRegistrationBean<StatViewServlet> statViewServlet() {
        ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*");
        Map<String, String> initParams = new HashMap<String, String>(16);
        //用户名
        initParams.put("loginUsername", "admin");
        //密码
        initParams.put("loginPassword", "123456");
        //IP白名单(没有配置或者为空,则允许所有访问)
        initParams.put("allow", "");
        //IP黑名单 (存在共同时,deny优先于allow)
        initParams.put("deny", "");
        bean.setInitParameters(initParams);


        return bean;
    }

    @Bean
    public FilterRegistrationBean<WebStatFilter> webStatFilter() {
        FilterRegistrationBean<WebStatFilter> bean = new FilterRegistrationBean<>();
        bean.setFilter(new WebStatFilter());


        Map<String, String> initParams = new HashMap<>(16);
        initParams.put("exclusions", "*.js,*.css,/druid/*");
        bean.setInitParameters(initParams);
        bean.setUrlPatterns(Arrays.asList("/*"));


        return bean;
    }
}

上面配置的就是访问路径和账号密码之类的,
搞好之后就可以通过

服务IP地址+服务名称+/druid/login.html
http://192.168.2.112/other/druid/index.html
访问

本机ip+运行服务端口号+/druid/login.html
http://192.168.1.101:6009/druid/login.html

注意配置了spring security记得放行 - /druid/**
服务IP地址+服务名称+/druid/login.html这种方式我这边会报权限问题刷新一下自动跳转成本机ip+运行服务端口号+/druid/login.html不知道为什么,明明放行了emm

引用 完全实现 Springboot2.x + druid1.1.x配置多数据源并实现自动切换

GitHub 加速计划 / druid / druid
6
3
下载
阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池
最近提交(Master分支:6 天前 )
81ebdebf * fix test checkstyle * fix testcase * fix testcase * fix checkstyle 1 天前
8917bb77 - 5 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐