Druid监控 + 多数据源配置

这篇具有很好参考价值的文章主要介绍了Druid监控 + 多数据源配置。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

先贴一下用的依赖项。


      <!-- druid 数据库连接池-->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>1.2.20</version>
		</dependency>
		<!-- mysql 驱动-->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
		</dependency>
		<!-- mybatis-plus -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.5.3.1</version>
		</dependency>
		<!--	多数据源-->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
			<version>3.5.2</version>
		</dependency>


	<!-- 上面是必须的 -->

	<!--spring-boot-web-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

	<!--	代码生成器插件-->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-generator</artifactId>
			<version>3.5.3.1</version>
		</dependency>
	<!-- 模版引擎 -->
		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
		</dependency>
	<!--	lombok-->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>
		<!--huttol工具类-->
		<dependency>
			<groupId>cn.hutool</groupId>
			<artifactId>hutool-all</artifactId>
			<version>5.8.11</version>
		</dependency>





		

application.yaml

yaml配置文件的配置。

# 数据源配置
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    druid:
      # ps
      # 主库数据源
      master:
        url: jdbc:mysql://localhost:3306/jzm?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: 123456
      # 从库数据源
      slave:
        # 从数据源开关/默认关闭
        enabled: false
        url:
        username:
        password:
      # 初始连接数
      initialSize: 5
      # 最小连接池数量
      minIdle: 10
      # 最大连接池数量
      maxActive: 20
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置连接超时时间
      connectTimeout: 30000
      # 配置网络超时时间
      socketTimeout: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      # 配置一个连接在池中最大生存的时间,单位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # 配置检测连接是否有效
      validationQuery: SELECT 1 FROM DUAL
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      webStatFilter:
        enabled: true
      statViewServlet:
        enabled: true
        # 设置白名单,不填则允许所有访问
        allow:
        url-pattern: /druid/*
        # 控制台管理用户名和密码
        login-username: ruoyi
        login-password: 123456
      filter:
        stat:
          enabled: true
          # 慢SQL记录
          log-slow-sql: true
          slow-sql-millis: 1000
          merge-sql: true
        wall:
          config:
            multi-statement-allow: true

DruidConfig

负责读取yaml文件的数据源配置,生成数据源。还有创建动态数据源容器。另外ServletRegistrationBean 和 FilterRegistrationBean的配置和生成。


/**
 * druid 配置多数据源
 *
 * @author jzm
 */
@Configuration
public class DruidConfig
{
    // 读取主数据源配置
    @Bean
    @ConfigurationProperties("spring.datasource.druid.master")
    public DataSource masterDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }

    // 读取从数据源配置(默认关闭)
    @Bean
    @ConfigurationProperties("spring.datasource.druid.slave")
    @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
    public DataSource slaveDataSource(DruidProperties druidProperties)
    {
        DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
        return druidProperties.dataSource(dataSource);
    }


    // 创建动态数据源容器
    @Bean(name = "dynamicDataSource")
    @Primary  
    public DynamicDataSource dataSource(DataSource masterDataSource)
    {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);

        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource"); 

        return new DynamicDataSource(masterDataSource, targetDataSources);
    }

    /**
     * 设置数据源
     *
     * @param targetDataSources 备选数据源集合
     * @param sourceName        数据源名称
     * @param beanName          bean名称
     */
    public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
    {
        try
        {
            DataSource dataSource = SpringUtil.getBean(beanName); // 从spring容器获得,bean实例
            targetDataSources.put(sourceName, dataSource);
        } catch (Exception e)
        {
        }
    }

    /**
     * 去除监控页面底部的广告
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    @Bean
    @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
    // 只有当这个配置为true是,这个bean才会被创建
    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
    {
        // 获取web监控页面的参数
        DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
        // 提取common.js的配置路径
        String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
        String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
        final String filePath = "support/http/resources/js/common.js";
        // 创建filter进行过滤
        Filter filter = new Filter()
        {
            @Override
            public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
            {
            }

            @Override
            public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                    throws IOException, ServletException
            {
                chain.doFilter(request, response);
                // 重置缓冲区,响应头不会被重置
                response.resetBuffer();
                // 获取common.js
                String text = Utils.readFromResource(filePath);
                // 正则替换banner, 除去底部的广告信息
                text = text.replaceAll("<a.*?banner\"></a><br/>", "");
                text = text.replaceAll("powered.*?shrek.wang</a>", "");
                response.getWriter().write(text);
            }

            @Override
            public void destroy()
            {
            }
        };
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        registrationBean.setFilter(filter);
        registrationBean.addUrlPatterns(commonJsPattern);
        return registrationBean;
    }


    /**
     * @description 注册一个StatViewServlet,进行druid监控页面配置
     * @return servlet registration bean
     */
    @Bean
    public ServletRegistrationBean druidStatViewServlet() {
        //先配置管理后台的servLet,访问的入口为/druid/
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
                new StatViewServlet(), "/druid/*");
        // IP白名单 (没有配置或者为空,则允许所有访问)
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // IP黑名单 (存在共同时,deny优先于allow)
        servletRegistrationBean.addInitParameter("deny", "");
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "123456");
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }



}

DynamicDataSource

就是我们的动态数据源,负责继承和初始化 AbstractRoutingDataSource。还有就是重写determineCurrentLookupKey()这个方法,让druid知道我们当前线程要使用那个数据源从而切换那个数据源。

/**
 * 动态数据源
 *
 * @author jzm
 */
public class DynamicDataSource extends AbstractRoutingDataSource
{
    public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources)
    {
        super.setDefaultTargetDataSource(defaultTargetDataSource);
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
    }


    /**
     * 获取当前线程正在用的数据源
     */
    @Override
    protected Object determineCurrentLookupKey()
    {
        return DynamicDataSourceContextHolder.getDataSourceType();
    }

    public static void setDataSource(String dataSource){
        DynamicDataSourceContextHolder.setDataSourceType(dataSource);
    }

    public static void clearDataSource(){
        DynamicDataSourceContextHolder.clearDataSourceType();
    }
}

DynamicDataSourceContextHolder

动态数据源上下文容器。

/**
 * 数据源切换处理
 *
 * @author jzm
 */
public class DynamicDataSourceContextHolder
{
    public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);

    /**
     * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本,
     * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。
     */
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();

    /**
     * 设置数据源的变量
     */
    public static void setDataSourceType(String dsType)
    {
        log.info("切换到{}数据源", dsType);
        CONTEXT_HOLDER.set(dsType);
    }

    /**
     * 获得数据源的变量
     */
    public static String getDataSourceType()
    {
        return CONTEXT_HOLDER.get();
    }

    /**
     * 清空数据源变量
     */
    public static void clearDataSourceType()
    {
        CONTEXT_HOLDER.remove();
    }
}

DataSourceType

数据源类型。

/**
 * 数据源
 * 
 * @author jzm
 */
public enum DataSourceType
{
    /**
     * 主库
     */
    MASTER,

    /**
     * 从库
     */
    SLAVE
}

DruidProperties

读取我们yml配置文件的类。


/**
 * druid 数据源配置读取类
 *
 * @author jzm
 */
@Configuration
public class DruidProperties
{
    @Value("${spring.datasource.druid.initialSize}")
    private int initialSize;

    @Value("${spring.datasource.druid.minIdle}")
    private int minIdle;

    @Value("${spring.datasource.druid.maxActive}")
    private int maxActive;

    @Value("${spring.datasource.druid.maxWait}")
    private int maxWait;

    @Value("${spring.datasource.druid.connectTimeout}")
    private int connectTimeout;

    @Value("${spring.datasource.druid.socketTimeout}")
    private int socketTimeout;

    @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
    private int timeBetweenEvictionRunsMillis;

    @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
    private int minEvictableIdleTimeMillis;

    @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
    private int maxEvictableIdleTimeMillis;

    @Value("${spring.datasource.druid.validationQuery}")
    private String validationQuery;

    @Value("${spring.datasource.druid.testWhileIdle}")
    private boolean testWhileIdle;

    @Value("${spring.datasource.druid.testOnBorrow}")
    private boolean testOnBorrow;

    @Value("${spring.datasource.druid.testOnReturn}")
    private boolean testOnReturn;

    public DruidDataSource dataSource(DruidDataSource datasource)
    {
        /** 配置初始化大小、最小、最大 */
        datasource.setInitialSize(initialSize);
        datasource.setMaxActive(maxActive);
        datasource.setMinIdle(minIdle);

        /** 配置获取连接等待超时的时间 */
        datasource.setMaxWait(maxWait);
        
        /** 配置驱动连接超时时间,检测数据库建立连接的超时时间,单位是毫秒 */
        datasource.setConnectTimeout(connectTimeout);
        
        /** 配置网络超时时间,等待数据库操作完成的网络超时时间,单位是毫秒 */
        datasource.setSocketTimeout(socketTimeout);

        /** 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 */
        datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

        /** 配置一个连接在池中最小、最大生存的时间,单位是毫秒 */
        datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
        datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);

        /**
         * 用来检测连接是否有效的sql,要求是一个查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。
         */
        datasource.setValidationQuery(validationQuery);
        /** 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 */
        datasource.setTestWhileIdle(testWhileIdle);
        /** 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
        datasource.setTestOnBorrow(testOnBorrow);
        /** 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 */
        datasource.setTestOnReturn(testOnReturn);
        return datasource;
    }
}

DataSource

我们自定义一个注解,标记我们当前注解的方法那个数据源。

/**
 * 自定义多数据源切换注解
 *
 * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准
 *
 * @author jzm
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource
{
    /**
     * 切换数据源名称
     */
     DataSourceType value() default DataSourceType.MASTER;
}

DataSourceAsept

我们定义一个切面类,负责获取我们的自定义数据源注解的值,从而在DynamicDataSource中的setDataSource() 方法,设置当前线程用的数据源。然后被determineCurrentLookupKey()方法获取到,从而切换数据源。注意在我们处理中方法的优先级比类的优先级高。


/**
 * 数据源切面类
 *
 * @author jzm
 */
@Aspect
@Component
public class DataSourceAspect implements Ordered {

    Logger log = LoggerFactory.getLogger(DataSourceAspect.class);

    @Pointcut("@annotation(com.example.annotation.DataSource)")
    public void dataSourcePointCut() {

    }

    @Around("dataSourcePointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {

        MethodSignature signature = (MethodSignature) point.getSignature();
        // 处理方法
        Method method = signature.getMethod();
        // 处理类
        Class<?> methodCls = method.getDeclaringClass();
        DataSource clsDs = methodCls.getAnnotation(DataSource.class);
        
        DataSource meDs = method.getAnnotation(DataSource.class);

        if (meDs == null ) {
            if(clsDs == null){
                log.debug("set datasource is " + DataSourceType.MASTER);
            }else{
                DynamicDataSource.setDataSource(clsDs.value().name());
                log.debug("set datasource is" + clsDs.value().name());
            }
        } else {
            DynamicDataSource.setDataSource(meDs.value().name());
            log.debug("set datasource is " + meDs.value().name());
        }

        try {
            return point.proceed();
        } finally {
            DynamicDataSource.clearDataSource();
            log.debug("clean datasource");
        }
    }

    @Override
    public int getOrder() {
        return 1;
    }
}

看到这,是已经把配置都能完了。

测试

我们随便找一张表负责数据库连接测试。

生成对应的service、mapper、controller文件。

这里就展示service实现类的写法。

 我们在对应的service实现里面。对想要切换数据源的方法标记@DataSource注解

@Service
@DataSource(value = DataSourceType.MASTER)
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {


    @Override
    @DataSource(value = DataSourceType.MASTER)
    public List<SysUser> findUserList() {
        return this.baseMapper.selectList(null);
    }


}

然后,启动项目。

访问sql监控页面

http://127.0.0.1:8080/druid/index.html  PS: ip和端口替换成自己的。

会出现一个登录页面。我们输入在DruidConfig中,配置好的用户名和密码。

    @Bean
    public ServletRegistrationBean druidStatViewServlet() {
        //先配置管理后台的servLet,访问的入口为/druid/
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(
                new StatViewServlet(), "/druid/*");
        // IP白名单 (没有配置或者为空,则允许所有访问)
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // IP黑名单 (存在共同时,deny优先于allow)
        servletRegistrationBean.addInitParameter("deny", "");
        servletRegistrationBean.addInitParameter("loginUsername", "admin");
        servletRegistrationBean.addInitParameter("loginPassword", "123456");
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

Druid监控 + 多数据源配置,# Springboot,java,数据库,多数据源,mysql

 登录完毕,出现如下页面,代表我们druid监控配置是没问题的。

Druid监控 + 多数据源配置,# Springboot,java,数据库,多数据源,mysql

但是,这时候由于项目并没有crud操作,因此数据源后面sql监控信息都是空的。

利用postman进行测试。

Druid监控 + 多数据源配置,# Springboot,java,数据库,多数据源,mysql

再打开数据源页面,出现如下所示,代表成功了。

Druid监控 + 多数据源配置,# Springboot,java,数据库,多数据源,mysql

多数据源配置验证

我们在进行curd操作时,嗯出现如下,代表数据源切换应该成功。文章来源地址https://www.toymoban.com/news/detail-814023.html

Druid监控 + 多数据源配置,# Springboot,java,数据库,多数据源,mysql

到了这里,关于Druid监控 + 多数据源配置的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JAVA:Springboot动态装配Druid多数据源

    1、简介 最近打算搭建一个鉴权中心服务,采用springboot+FastMybatis装配Druid,考虑后续拓展采用Druid多数据源配置,以一个数据源为主,多个动态数据源为辅的结构。除了数据库,后续会结合shiro安全框架来搭建。 2、引用 在pom.xml添加框架Springboot +FastMybatis + Druid相关maven引用。

    2024年02月09日
    浏览(48)
  • springboot配置自定义数据源(Druid德鲁伊)的步骤。

    今天和大家分享下在Springboot中配置自定义数据源Druid的两种方法及步骤。 方法一: 1.在pom.xml配置依赖(注释里面的内容) 2.配置自己的数据源设置,我是在yaml文件中配置的,顺便提醒一下,在配置yaml文件的时候缩进问题一定要注意,不然无法读取到就会报错。 spring: datasourc

    2024年02月15日
    浏览(58)
  • SpringBoot整合(五)HikariCP、Druid数据库连接池—多数据源配置

    在项目中,数据库连接池基本是必不可少的组件。在目前数据库连接池的选型中,主要是 Druid ,为 监控 而生的数据库连接池。 HikariCP ,号称 性能 最好的数据库连接池。 在Spring Boot 2.X 版本,默认采用 HikariCP 连接池。而阿里大规模采用 Druid 。下面介绍在SpringBoot中使用Hika

    2024年02月17日
    浏览(79)
  • SpringBoot整合Mybatis-Plus、Druid配置多数据源

    目录 1.初始化项目 1.1.初始化工程 1.2.添加依赖 1.3.配置yml文件 1.4.Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹 1.5.配置使用数据源 1.5.1.注解方式 1.5.2.基于AOP手动实现多数据源原生的方式 2.结果展示 Mybatis-Plus:简介 | MyBatis-Plus (baomidou.com) 在正式开始之前,先初始

    2024年02月11日
    浏览(48)
  • Dynamic DataSource 多数据源配置【 Springboot + DataSource + MyBatis Plus + Druid】

    MybatisPlus多数据源配置主要解决的是多数据库连接和切换的问题。在一些大型应用中,由于数据量的增长或者业务模块的增多,可能需要访问多个数据库。这时,就需要配置多个数据源。 2.1.1、引用依赖 2.1.2、application.yml 配置 2.1.3、通用配置类 2.1.4、使用方式 这里便不过多的

    2024年02月03日
    浏览(48)
  • SpringBoot3整合Druid数据源的解决方案

    druid-spring-boot-3-starter目前最新版本是1.2.20,虽然适配了SpringBoot3,但缺少自动装配的配置文件,会导致加载时报加载驱动异常。 需要手动在resources目录下创建 META-INF/spring/ 目录,并且在 META-INF/spring/ 创建 org.springframework.boot.autoconfigure.AutoConfiguration.imports , 文件中添加如下内容

    2024年03月09日
    浏览(106)
  • SpringBoot -02 SpringBoot整合Mybatis、Druid数据源、单元测试、JSP

    mybatis起步依赖 mysql启动依赖 数据源配置 mybatis相关配置 加载mybatis配置文件 mybatis别名配置 日志配置 加载mapper映射文件配置文件 http://localhost:8080/users Druid连接池后台监控:http://localhost:8080/druid/index.html SpringBoot对JSP的支持不是很友好,所以JSP很少被使用 springboot 不支持jsp 但是

    2024年02月06日
    浏览(91)
  • SpringBoot整合Druid数据库连接池&多数据源&注解切换&动态添加

    配置好之后 Druid 会通过 DruidDataSourceAutoConfigure 自动装配 属性配置 数据源枚举 动态数据源 继承 AbstractRoutingDataSource 就可以实现动态数据源了 实现了一个动态数据源类的构造方法,主要是为了设置默认数据源,以及以Map保存的各种目标数据源。其中Map的key是设置的数据源名称

    2024年03月22日
    浏览(68)
  • SpringBoot整合Mybatis-Plus+Druid实现多数据源

    🌺本文主要讲解 springboot +mybatisplus + druid 实现多数据源配置功能 🌺 主页传送门:📀 传送 Spring Boot:    Spring Boot是一个基于Spring框架的开源Java开发框架,旨在简化Spring应用程序的开发、配置和部署。它提供了一种快速、敏捷的方式来构建独立的、生产级别的Spring应用程

    2024年02月09日
    浏览(104)
  • 【SpringBoot 3.x】整合Mybatis-Plus多数据源、Druid

    开发依赖 版本 Spring Boot 3.0.6 Mybatis-Plus 3.5.3.1 dynamic-datasource-spring-boot-starter 3.6.1 JDK 20 SpringBoot启动类修改 由于排除了DruidDataSourceAutoConfigure类的自动装载,就需要手工指定装配以下几个类 查看DruidDataSourceAutoConfigure这个类的源码可以看出,需要把@Import带进来的几个类进行自动装

    2024年02月04日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包