介绍

Druid Spring Boot Starter 用于帮助你在Spring Boot项目中轻松集成Druid数据库连接池、监控、防SQL注入和日志等用途的Filter。(吐槽下官网的文档实在太乱了,国外的开源项目文档真的好太多了)

使用

1.使用yml进行主从服务器的配置,若还有可以slave-one、slave-two继续加。也可以用java bean配置,这里不再列举。

# 数据源配置
spring:
    datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driverClassName: com.mysql.cj.jdbc.Driver
        druid:
            # 主库数据源
            master:
                url: jdbc:mysql://localhost:3306/business?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                username: jianghao
                password: JiangHao
            # 从库数据源
            slave:
                # 从数据源开关/默认关闭
                enabled: false
                url: 
                username: 
                password: 
            # 初始连接数
            initialSize: 5
            # 最小连接池数量
            minIdle: 10
            # 最大连接池数量
            maxActive: 20
            # 配置获取连接等待超时的时间
            maxWait: 60000
            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
            timeBetweenEvictionRunsMillis: 60000
            # 配置一个连接在池中最小生存的时间,单位是毫秒
            minEvictableIdleTimeMillis: 300000
            # 配置一个连接在池中最大生存的时间,单位是毫秒
            maxEvictableIdleTimeMillis: 900000
            # 配置查询DUL虚拟表检测连接是否有效。(DUAL is purely for the convenience of people who require that all SELECT statements should have FROM and possibly other clauses. MySQL
            # may ignore the clauses. MySQL does not require FROM DUAL if no tables)
            validationQuery: SELECT 1 FROM DUAL
            # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。
            testWhileIdle: true
            # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
            testOnBorrow: false
            # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。
            testOnReturn: false
            webStatFilter:
                # 开启web监控数据的采集(监控的数据可以在【URI监控】页面看到)
                enabled: true
                # 不监控下面的地址,多个用,隔开
                exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
            statViewServlet:
                # 配置监控页面的展示
                enabled: true
                # 设置白名单,不填则允许所有访问
                allow:
                # 禁止本地的ip访问
                # deny: 127.0.0.1,localhost
                url-pattern: /druid/*
                # 进入控制台管理用户名和密码
                login-username: 
                login-password:
            filter:
                stat:
                    enabled: true
                    # 慢SQL记录
                    log-slow-sql: true
                    slow-sql-millis: 1000
                    merge-sql: true
                wall:
                    config:
                        # 是否允许一次执行多条语句,默认false
                        multi-statement-allow: true

2.自定义一个注解,对使用数据库的方法或类进行注解,使用主或从数据库

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DataSource
{
    /**
     * 切换数据源名称
     */
    public DataSourceType value() default DataSourceType.MASTER;
}

3.配置AOP类,对注解的方法或类进行切换数据源操作

@Aspect
@Order(1)
@Component
public class DataSourceAspect
{
    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
            + "|| @within(com.ruoyi.common.annotation.DataSource)")
    public void dsPointCut()
    {

    }

    @Around("dsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable
    {
        DataSource dataSource = getDataSource(point);

        if (StringUtils.isNotNull(dataSource))
        {
            DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
        }

        try
        {
            return point.proceed();
        }
        finally
        {
            // 销毁数据源 在执行方法之后
            DynamicDataSourceContextHolder.clearDataSourceType();
        }
    }

    /**
     * 获取需要切换的数据源
     */
    public DataSource getDataSource(ProceedingJoinPoint point)
    {
        MethodSignature signature = (MethodSignature) point.getSignature();
        DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
        if (Objects.nonNull(dataSource))
        {
            return dataSource;
        }

        return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
    }
}

4.配置数据源,实现druid的方法,方便aop进行数据源切换操作

@Configuration
public class DruidConfig
{

    /**
     *  DynamicDataSource继承AbstractRoutingDataSource去实现了determineCurrentLookupKey方法,在操作数据库之前druid会操作
     *  该方法获取key,用来判断当前需要使用的是主库还是从库
     */
    @Bean(name = "dynamicDataSource")
    @Primary
    public DynamicDataSource dataSource(DataSource masterDataSource)
    {
        // 将主从库初始化,并添加到DynamicDataSource中去
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
        setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
        return new DynamicDataSource(masterDataSource, targetDataSources);
    }

    @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);
    }
}

属性说明

连接池属性

配置

默认值

说明

url


连接数据库的url,不同数据库不一样。

username


连接数据库的用户名

password


连接数据库的密码

maxActive

8

最大连接池数量

详细配置

监控配置

WebStatFilter用于采集web-jdbc关联监控的数据,详细请参考

spring.datasource.druid.web-stat-filter.enabled= #是否启用StatFilter默认值false
spring.datasource.druid.web-stat-filter.url-pattern=
spring.datasource.druid.web-stat-filter.exclusions=
spring.datasource.druid.web-stat-filter.session-stat-enable=
spring.datasource.druid.web-stat-filter.session-stat-max-count=
spring.datasource.druid.web-stat-filter.principal-session-name=
spring.datasource.druid.web-stat-filter.principal-cookie-name=
spring.datasource.druid.web-stat-filter.profile-enable=

StatViewServlet用于展示Druid的统计信息,提供的html和json api,详细请参考

spring.datasource.druid.stat-view-servlet.enabled= #是否启用StatViewServlet(监控页面)默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
spring.datasource.druid.stat-view-servlet.url-pattern=
spring.datasource.druid.stat-view-servlet.reset-enable=
spring.datasource.druid.stat-view-servlet.login-username=
spring.datasource.druid.stat-view-servlet.login-password=
spring.datasource.druid.stat-view-servlet.allow=
spring.datasource.druid.stat-view-servlet.deny=

# Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置
spring.datasource.druid.aop-patterns= # Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔

配置Filter

配置StatFilter,用于统计监控信息,详细请参考

spring.datasource.druid.filter.stat.enabled=true
spring.datasource.druid.filter.stat.db-type=h2
# 开启慢查询日志
spring.datasource.druid.filter.stat.log-slow-sql=true
# 超过2000毫秒视慢查询
spring.datasource.druid.filter.stat.slow-sql-millis=2000

WallFilter的功能是防御SQL注入攻击。它是基于SQL语法分析,理解其中的SQL语义,然后做处理的,智能,准确,误报率低。详细请参考

spring.datasource.druid.filter.wall.enabled=true
spring.datasource.druid.filter.wall.db-type=h2
spring.datasource.druid.filter.wall.config.delete-allow=false
spring.datasource.druid.filter.wall.config.drop-table-allow=false

其他的Filter

  • 用于统计监控信息
  • 防御SQL注入攻击
  • 从配置文件中读取配置
  • 从远程http文件中读取配置
  • 为数据库密码提供加密功能
  • 由于历史原因,一些数据库保存数据的时候使用了错误编码,需要做编码转换。
  • Slf4jLogFilter
  • Log4jFilter
  • Log4j2Filter
  • CommonsLogFilter

配置log

Druid中使用log4j2进行日志输出