SpringBoot3.x + MybatisPlus + Druid 多数据源配置及开启Druid监控与统计功能

现在开发服务器的时候,SpringBoot3.x + MybatisPlus + Druid 多数据源配置基本上是标准配置了。本Druid数据源也支持多数据源配置,但是MyBatis Plus团队也提供了一个多数据源的管理组件,他们重写了部分功能,所以在配置上与原生的Druid配置有些不一样。

添加maven依赖

复制代码
<!-- 阿里数据库连接池 -->
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid-spring-boot-3-starter -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-3-starter</artifactId>
            <version>1.2.22</version>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.5</version>
            <exclusions>
                <exclusion>
                    <groupId>org.mybatis</groupId>
                    <artifactId>mybatis-spring</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>3.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-annotation</artifactId>
            <version>3.5.5</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>
        <!-- 动态数据源 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
            <version>4.2.0</version>
        </dependency>

Mybatis Plus的多数据源自动装配的类是:

它的配置类中也Import了阿里地的Druid配置

因为同时存在了两个数据源的实现,所以在启动的时候,需要把阿里的数据源装配类去掉

配置

复制代码
# 数据源配置
spring:
  data:
    redis:
      host: 192.168.3.102
      port: 6379
      password: 123456
  datasource:
    druid:
      filter:
        stat:
          enabled: true
      # 开启druid的sql统计及监控,注意这里配置的时候idea不会提示,估计是因为是去掉阿里数据源的问题
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
        # 控制台管理用户名和密码,记得生产环境的时候,此接口最好是在安全的环境中访问
        login-username: admin
        login-password: 123456
        reset-enable: false
        allow: 192.168.3.25,127.0.0.1  # 允许访问的ip白名单
      web-stat-filter:
        enabled: true
        url-pattern: /*
    
    type: com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.cj.jdbc.Driver
    dynamic:
      primary: master
      lazy: false
      datasource:
        # 主库数据源
        master:
          url: jdbc:mysql://192.168.3.102:3306/ciyan_mmo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: 123456
        # 从库数据源
        #        slave:
        #          url:
        #          username:
        #          password:
      druid:
        # 初始连接数
        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
        filters: stat,wall

启动服务后,就可以访问了:http://127.0.0.1:9901/druid/login.html

端口是启动的web服务的端口


如查你访问的login.html时,显示的是一个空白页面,说明服务器没有reponse返回,这个有可能是你自己写的过滤器导致把response的响应内容重写或过滤掉了。例如使用了ContentCachingResponseWrapper,但是在最后响应的时候没有copyBodyToResponse,正确的应该这样写:

复制代码
package cn.jw.starter.web.core.filters;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import org.springframework.web.util.WebUtils;

import cn.hutool.extra.spring.SpringUtil;
import cn.jw.starter.web.core.properties.JwWebProperties;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * 缓存请求消息的filter,
 *
 * @author 王广帅
 * @since 2024/4/3 20:31
 */
public class CacheRequestBodyFilter extends OncePerRequestFilter {

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
        String uri = request.getRequestURI();
        // 静态资源都不要走这个过滤
        if (uri.endsWith(".html") || uri.endsWith(".js") || uri.endsWith(".css") || uri.endsWith(".ico")) {
            return true;
        }
        JwWebProperties jwWebProperties = SpringUtil.getBean(JwWebProperties.class);
        if (jwWebProperties.getIgnoreCacheBodyUriList().contains(uri)) {
            return true;
        }
        return super.shouldNotFilter(request);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
        throws ServletException, IOException {
        logger.debug("先走一步");
        if (request.getContentLength() > 0 && !(request instanceof ContentCachingRequestWrapper)) {
            request = new ContentCachingRequestWrapper(request);
            request.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        }
        if (!(response instanceof ContentCachingResponseWrapper)) {
            response = new ContentCachingResponseWrapper(response);
            response.setCharacterEncoding(StandardCharsets.UTF_8.displayName());
        }
        filterChain.doFilter(request, response);
        updateResponse(response);
    }

    /**
     * 更新响应(不操作这一步,会导致接口响应空白)
     *
     * @param response
     *            响应对象
     * @throws IOException
     *             /
     */
    private void updateResponse(HttpServletResponse response) throws IOException {
        ContentCachingResponseWrapper responseWrapper =
            WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
        if (responseWrapper != null) {
            Objects.requireNonNull(responseWrapper).copyBodyToResponse();
        }
    }
}

之前我就是这样,把updateReponse写到HandlerInterceptor的实现类中了,但是HandlerInterceptor只是拦截Controller里面的操作,像Druid 的监控信息请求的是Servlet,不会走HandlerInterceptor。

相关推荐
天丁o15 小时前
Spring Boot + MyBatis Plus 考勤日报统计报表:打卡记录聚合、异常分类和明细下钻 Demo
spring boot·mybatis plus·企业数字化·考勤系统·报表统计
ruleslol3 天前
Mybatis-Plus15: 悲观锁 & 乐观锁
mybatis plus
天丁o3 天前
Spring Boot 考勤异常申诉审批闭环:缺卡、补卡、审核回写和日统计重算 Demo
spring boot·mybatis plus·企业数字化·考勤系统·审批流
天丁o1 个月前
Spring Boot + uni-app 智慧考勤闭环 Demo:打卡记录、异常状态和日统计如何复用到企业系统
spring boot·uni-app·mybatis plus·企业管理系统·考勤系统
小坏讲微服务3 个月前
SpringBoot4.0整合Spring Security+MyBatis Plus完整权限框架实现
java·spring·mybatis·spring security·mybatis plus·springboot4.0
诺浅4 个月前
聊聊@DSTransactional的坑
java·多数据源·dstransavtional
玄〤5 个月前
个人博客网站搭建day5--MyBatis-Plus核心配置与自动填充机制详解(漫画解析)
java·后端·spring·mybatis·springboot·mybatis plus
好好研究6 个月前
MyBatis - Plus(二)常见注解 + 常见配置
数据库·spring boot·mybatis·mybatis plus
九皇叔叔6 个月前
【07】SpringBoot3 MybatisPlus 删除(Mapper)
java·开发语言·mybatis·mybatis plus