springboot整合druid连接池,sql监控与mybatis参数优化


Druid简介

Druid是阿里出品的。
Druid是Java语言中最好的数据库连接池,能够提供强大的监控和扩展功能。

官方文档(英文):https://github.com/alibaba/druid/

官方归纳driud的常见问题

本文 springboot 2.3.7.RELEASE + (mybatis2.1.3 +pagehelper)
来整合 Druid(1.1.22) 连接池


一、boot结构

在这里插入图片描述
表数据
在这里插入图片描述
在这里插入图片描述

二、集成示例

1.1、引入依赖

<!--
     阿里druid连接池
     1.1.23不能使用,大量ERROR问题:
     discard long time none received connection
     原因和方案:https://zhuanlan.zhihu.com/p/368683245
 -->
 <dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid-spring-boot-starter</artifactId>
     <version>1.1.22</version>
 </dependency>

 <!--mysql依赖85多了ssl-->
 <dependency>
     <groupId>mysql</groupId>
     <artifactId>mysql-connector-java</artifactId>
     <version>8.0.19</version>
 </dependency>

 <!--mybatis-->
 <dependency>
     <groupId>org.mybatis.spring.boot</groupId>
     <artifactId>mybatis-spring-boot-starter</artifactId>
     <version>2.1.3</version>
 </dependency>
 <!--分页插件-->
 <dependency>
     <groupId>com.github.pagehelper</groupId>
     <artifactId>pagehelper-spring-boot-starter</artifactId>
     <version>1.2.12</version>
 </dependency>

 <!-- StringUtils工具类 -->
 <dependency>
     <groupId>org.apache.commons</groupId>
     <artifactId>commons-lang3</artifactId>
     <version>${commons-lang3.version}</version>
 </dependency>

1.2、配置文件application.properties

MySQL+druid+mybatis+pagehelper 详细配置

# 应用名称
spring.application.name=springtaskdemo
# 应用服务 WEB 访问端口
server.port=8080

#======================↓↓↓↓↓↓↓↓↓↓↓↓↓↓=======================================
# 配置数据源 mysql8
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone\=Asia/Shanghai&useUnicode\=true&characterEncoding\=utf8&allowMultiQueries\=true&rewriteBatchedStatements\=true
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

#  ===== ↓使用druid数据源↓ ========
# 注明:druid连接池springboot暂无法默认支持,需要自己配置bean
# 连接池类型
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
# 连接池初始化连接数量
spring.datasource.initialSize=5
# 连接池最小空闲数
spring.datasource.minIdle=5
# 连接池最大活跃连接数
spring.datasource.maxActive=20
# 配置获取连接等待超时的时间(毫秒)
spring.datasource.maxWait=60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
spring.datasource.minEvictableIdleTimeMillis=60000
# 连接是否有效的查询语句(心跳语句)
spring.datasource.validationQuery=SELECT 1 FROM DUAL

#........开始.................
# testOnBorrow和testOnReturn在生产环境一般是不开启的,主要是性能考虑。失效连接主要通过testWhileIdle
# 保证每次获取连接时候都要到数据库验证连接有效性, 这在高并发的时候会造成性能下降,可以将testOnBorrow设置成false,testWhileIdle设置成true这样能获得比较好的性能
# testWhileIdle默认true,则验证这条连接是否可用。
spring.datasource.testWhileIdle=true
# testOnBorrow默认为false,当应用向连接池申请连接时,连接池会判断这条连接是否是可用的
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
#.........结束................

# *********开始***********
#开发时候打开,上线关闭。poolPreparedStatements有可能会导致oom。内存泄露
#打开PSCache,并且指定每个连接上PSCache(游标)的大小 【poolPreparedStatements默认为 false】
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
# 生产环境中不要开启Druid的removeAbandoned配置,【默认fasle,开发调试用true】
spring.datasource.removeAbandoned=true
# *********结束***********

# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,【 'stat':监控统计  'wall':用于防火墙,防御sql注入   'slf4j':日志 】
spring.datasource.filters=stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
#useGlobalDataSourceStat: true  # 合并多个DruidDataSource的监控数据(多数据源)
# SQL监控后台登录用户名-自定义
spring.datasource.loginUsername:admin
# SQL监控后台登录用户密码-自定义
spring.datasource.loginPassword:admin
#====================↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑===================================================


#======================↓↓↓↓mybatis配置-开始↓↓↓↓======================
# 映射文件xml的位置
mybatis.mapper-locations=classpath:mapper/*Mapper.xml
# 使全局的映射器启用或禁用缓存
mybatis.configuration.cache-enabled=true
# 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载
mybatis.configuration.lazy-loading-enabled=true
# 当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。
mybatis.configuration.aggressive-lazy-loading=false
# 是否允许单条sql 返回多个数据集 (取决于驱动的兼容性) 默认:true
mybatis.configuration.multiple-result-sets-enabled=true
# 是否可以使用列的别名 (取决于驱动的兼容性) 默认:true
mybatis.configuration.use-column-label=true
# 指定MyBatis如何自动映射 数据基表的列 NONE:不隐射 PARTIAL:部分 FULL:全部
mybatis.configuration.auto-mapping-behavior=partial
# 这是默认的执行类型 (SIMPLE: 简单; REUSE: 执行器可能重复使用prepared statements语句;BATCH: 执行器可以重复执行语句和批量更新)
mybatis.configuration.default-executor-type=simple
# sql执行时间超时时间
mybatis.configuration.default-statement-timeout=25
# 允许在嵌套语句中使用分页(RowBounds)。如果允许使用则设置为false。
mybatis.configuration.safe-row-bounds-enabled=false
# 是否使用驼峰命名法转换字段
mybatis.configuration.map-underscore-to-camel-case=false
# 设置本地缓存范围 session:就会有数据的共享 statement:语句范围 (这样就不会有数据的共享 ) 默认:session
mybatis.configuration.local-cache-scope=session
# 设置当JDBC类型为空时,某些驱动程序 要指定值,默认:OTHER。当写入null值的字段时,部分数据库需要指定null的数据类型.mysql不用设置。【oracle需要设置】对应org.apache.ibatis.type.JdbcType的枚举值
mybatis.configuration.jdbc-type-for-null=other
# 指定对象哪个的方法触发一次延迟加载
mybatis.configuration.lazy-load-trigger-methods=equals,clone,hashCode,toString
# [默认false,推荐使用true] 如果数据为空的字段,则该字段省略不显示,查询数据映射数据类型使用的是Map。当字段值为null时,mybatis映射返回字段的时候会忽略,而原接口是null值也返回,为了兼容,需要设置不忽略null字段
mybatis.configuration.call-setters-on-nulls=true
# mybatis指定日志输出的前缀
mybatis.configuration.log-prefix=mybatis_
# 打印sql-开发时启用,会影响性能【使用boot默认的logback】
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

# 将java类型(javaType)转化为jdbc类型(jdbcType),或者将jdbc类型(jdbcType)转化为java类型(javaType)。【这个参数还没搞得很明白】
# mybatis.type-handlers-package=com.mapper.typehandler
# 允许JDBC生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。 默认:false
# mybatis.configuration.use-generated-keys=false
# 指定代理工厂:mybatis 实现2个:CglibProxyFactory和JavassistProxyFactory(默认)
# mybatis.configuration.proxy-factory=CGLIB
#====================↑↑↑↑↑mybatis配置-结束↑↑↑↑↑↑===================================================


# pagehelper分页插件
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql

1.3、编写druid配置类

package sqy.springtaskdemo.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
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 org.springframework.context.annotation.Scope;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

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

/**
 * Druid核心配置类 - 注册bean
 *  Druid连接池监控平台 http://127.0.0.1:8080/druid/index.html
 * @author suqinyi
 * @Date 2022/1/10
 */
@Configuration
public class DruidConfig {

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

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

    /**
     * 配置Druid监控
     *
     * @param :
     * @return: org.springframework.boot.web.servlet.ServletRegistrationBean
     */
    @Bean
    public ServletRegistrationBean druidServlet() {
        // 注册服务
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        // IP白名单(为空表示,所有的都可以访问,多个IP的时候用逗号隔开)
        servletRegistrationBean.addInitParameter("allow", "127.0.0.1");
        // IP黑名单 (存在共同时,deny优先于allow)
        servletRegistrationBean.addInitParameter("deny", "127.0.0.2");
        // 设置控制台登录的用户名和密码
        servletRegistrationBean.addInitParameter("loginUsername", loginUsername);
        servletRegistrationBean.addInitParameter("loginPassword", loginPassword);
        // 是否能够重置数据
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    /**
     * 配置web监控的filter
     *
     * @param :
     * @return: org.springframework.boot.web.servlet.FilterRegistrationBean
     */
    @Bean
    public FilterRegistrationBean webStatFilter() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        // 添加过滤规则
        Map<String, String> initParams = new HashMap<>(1);
        // 设置忽略请求
        initParams.put("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
        filterRegistrationBean.setInitParameters(initParams);
        filterRegistrationBean.addInitParameter("profileEnable", "true");
        filterRegistrationBean.addInitParameter("principalCookieName", "USER_COOKIE");
        filterRegistrationBean.addInitParameter("principalSessionName", "");
        filterRegistrationBean.addInitParameter("aopPatterns", "sqy.springtaskdemo.service");
        // 验证所有请求
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }

    /**
     * 配置数据源 【 将所有前缀为spring.datasource下的配置项都加载到DataSource中 】
     *
     * @param :
     * @return: javax.sql.DataSource
     */
    @Bean(name = "dataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return new DruidDataSource();
    }

    /**
     * 配置事物管理器
     *
     * @param :
     * @return: org.springframework.jdbc.datasource.DataSourceTransactionManager
     */
    @Bean(name = "transactionManager")
    public DataSourceTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }


    /**
     * ↓↓↓↓↓↓  配置spring监控  ↓↓↓↓↓↓
     * DruidStatInterceptor: druid提供的拦截器
     *
     * @param :
     * @return: com.alibaba.druid.support.spring.stat.DruidStatInterceptor
     */
    @Bean
    public DruidStatInterceptor druidStatInterceptor() {
        DruidStatInterceptor dsInterceptor = new DruidStatInterceptor();
        return dsInterceptor;
    }

    /**
     * 使用正则表达式配置切点
     *
     * @param :
     * @return: org.springframework.aop.support.JdkRegexpMethodPointcut
     */
    @Bean
    @Scope("prototype")
    public JdkRegexpMethodPointcut druidStatPointcut() {
        JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();
        pointcut.setPattern("sqy.springtaskdemo.controller.*");
        return pointcut;
    }

    /**
     * DefaultPointcutAdvisor类定义advice及 pointcut 属性。advice指定使用的通知方式,也就是druid提供的DruidStatInterceptor类,pointcut指定切入点
     *
     * @param druidStatInterceptor
     * @param druidStatPointcut:
     * @return: org.springframework.aop.support.DefaultPointcutAdvisor
     */
    @Bean
    public DefaultPointcutAdvisor druidStatAdvisor(DruidStatInterceptor druidStatInterceptor, JdkRegexpMethodPointcut druidStatPointcut) {
        DefaultPointcutAdvisor defaultPointAdvisor = new DefaultPointcutAdvisor();
        defaultPointAdvisor.setPointcut(druidStatPointcut);
        defaultPointAdvisor.setAdvice(druidStatInterceptor);
        return defaultPointAdvisor;
    }

}

1.4、启动类扫描mapper包

在这里插入图片描述

1.5、实体类

user表

package sqy.springtaskdemo.pojo;

/**
 * @author suqinyi
 * @Date 2022/1/11
 */
public class User {
    private Integer userId;
    private String userName;
    private String password;

   //省略get、set、tostring

调度表

package sqy.springtaskdemo.pojo;

/**
 * @author suqinyi
 * @Date 2022/1/10
 */
public class MyCronTask {
    private Integer cronId;
    private String cronTime;

   //省略get、set、tostring
}

1.6、Mybatis的xml方式

1.6.1、controller

package sqy.springtaskdemo.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import sqy.springtaskdemo.pojo.User;
import sqy.springtaskdemo.service.UserService;

import java.util.List;

/**
 * @author suqinyi
 * @Date 2022/1/11
 */
@RestController
public class UserController {
    @Autowired
    UserService userService;

    /**
     * http://localhost:8080/findAllUser
     * 基于xml方式(推荐)
     */
    @GetMapping("/findAllUser")
    public void findAll() {
        List<User> list = userService.findAll();
        System.out.println(list);
    }
}

1.6.2、service

接口

package sqy.springtaskdemo.service;

import sqy.springtaskdemo.pojo.User;

import java.util.List;

/**
 * @author suqinyi
 * @Date 2022/1/11
 */
public interface UserService {
    List<User> findAll();
}

实现

package sqy.springtaskdemo.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import sqy.springtaskdemo.mapper.UserMapper;
import sqy.springtaskdemo.pojo.User;
import sqy.springtaskdemo.service.UserService;

import java.util.List;

/**
 * @author suqinyi
 * @Date 2022/1/11
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserMapper userMapper;

    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }
}

1.6.3、mapper接口和xml文件

mapper接口

package sqy.springtaskdemo.mapper;
import sqy.springtaskdemo.pojo.User;
import java.util.List;

/**
 * @author suqinyi
 * @Date 2022/1/11
 * xml方式-推荐
 */
public interface UserMapper {

    List<User> findAll();
}

xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="sqy.springtaskdemo.mapper.UserMapper">

    <!-- 用户表的映射 -->
    <resultMap id="UserResultMap" type="sqy.springtaskdemo.pojo.User">
        <id column="user_id" jdbcType="INTEGER" property="userId"/>
        <result column="user_name" jdbcType="VARCHAR" property="userName"/>
        <result column="password" jdbcType="VARCHAR" property="password"/>
    </resultMap>

    <!--查找全部-->
    <select id="findAll" resultType="sqy.springtaskdemo.pojo.User" resultMap="UserResultMap">
        select * from user;
    </select>

</mapper>

1.7、Mybatis的注解方式

这边controller和service和上面类似,就省略了
不同就只有mapper接口,注解方式不需要xml文件。
但是还是推荐xml方式比较好

mapper接口

package sqy.springtaskdemo.mapper;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Repository;
import sqy.springtaskdemo.pojo.MyCronTask;

import java.util.List;

/**
 * @author suqinyi
 * @Date 2022/1/10
 * 注解方式
 */
public interface CronMapper {

	//查找注解。还有delete、insert、update...
    @Select("select * from cron_task")
    @Results(id="cronMap",value={
            @Result(id=true,column = "cron_id",property = "cronId"),
            @Result(column = "cron_time",property = "cronTime"),
    })
    List<MyCronTask> findAll();

}


三、效果:

1.1、druid监控

在这里插入图片描述

1.2、控制台效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

suqinyi

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值