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。

相关推荐
九皇叔叔9 天前
【07】SpringBoot3 MybatisPlus 删除(Mapper)
java·开发语言·mybatis·mybatis plus
九皇叔叔11 天前
【03】SpringBoot3 MybatisPlus BaseMapper 源码分析
java·开发语言·mybatis·mybatis plus
九皇叔叔11 天前
【04】SpringBoot3 MybatisPlus 查询(Mapper)
java·mybatis·mybatis plus
九皇叔叔13 天前
【01】SpringBoot3 MybatisPlus 工程创建
java·mybatis·springboot3·mybatis plus
小坏讲微服务2 个月前
Spring Boot 4.0 新特性整合 MyBatis-Plus 完整教程
java·spring boot·后端·spring cloud·微服务·mybatis·mybatis plus
小雨的光2 个月前
QuickDruid
spring boot·druid监控
小坏讲微服务2 个月前
Spring Boot 4.0 与 MyBatis Plus 整合完整指南
java·spring boot·后端·mybatis·springcloud·mybatis plus·java开发
小坏讲微服务2 个月前
SpringCloud整合Scala实现MybatisPlus实现业务增删改查
java·spring·spring cloud·scala·mybatis plus
后端小张3 个月前
【JAVA 进阶】Mybatis-Plus 实战使用与最佳实践
java·spring boot·spring·spring cloud·tomcat·mybatis·mybatis plus