SpringBoot + Druid + Mybatis-Plus + Mysql 实现数据库监控

news2024/11/18 15:24:54

1. 简介

  在日常的WEB开发中都会使用数据库存储信息。大多数情况我们只是使用了数据库,而无法感知业务对数据库的压力,从而无法有目的的提升性能。在使用数据库时,都会选用常见的C3P0DBCPHikariDruid连接池,虽然SpringBoot官方强调Hikari性能更好,但我更倾向于功能更加全面的Druid连接池。Druid是阿里巴巴生态中的一员,除了提供数据库连接池,还提供SQL解析、数据源监控的能力。
  Github地址:https://github.com/alibaba/druid

2. 相关博客

  DB SQL 转 ES DSL(支持多种数据库常用查询、统计、平均值、最大值、最小值、求和语法)

3. 示例代码

  • 创建数据库及初始化表数据
CREATE DATABASE `test`;

USE `test`;

DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `username` varchar(10) DEFAULT NULL COMMENT '用户名称',
  `sex` char(1) DEFAULT NULL COMMENT '性别',
  `phone` varchar(11) DEFAULT NULL COMMENT '手机号',
  PRIMARY KEY (`id`)
) COMMENT='用户表';

INSERT INTO `t_user`(`username`, `sex`, `phone`) VALUES ('张三', '1', '13500000000');
INSERT INTO `t_user`(`username`, `sex`, `phone`) VALUES ( '李四', '0', '18311111111');
INSERT INTO `t_user`(`username`, `sex`, `phone`) VALUES ( '王五', '1', '15522222222');
  • 创建项目
  • 修改pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.c3stones</groupId>
    <artifactId>spring-boot-druid-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.8</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.2.16</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3.1</version>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  • 配置数据源、监控等信息
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    # Druid配置
    druid:
      # 初始化连接池大小
      initial-size: 5
      # 连接池最小空闲数
      min-idle: 5
      # 连接池最大连接数
      max-active: 20
      # 连接时最大等待时间(单位:毫秒)
      max-wait: 60000
      # 检测关闭空闲连接的时间间隔(单位:毫秒)
      time-between-eviction-runs-millis: 60000
      # 保持空闲连接不被关闭的最小生存时间(单位:毫秒)
      min-evictable-idle-time-millis: 300000
      # 检测连接有效的SQL
      # 为空则test-while-idle、test-on-borrow、test-on-return配置失效
      validation-query: SELECT 1
      # 检测连接是否有效的超时时间
      validation-query-timeout: 1
      # 检测空闲连接
      # 不影响性能,建议开启
      test-while-idle: true
      # 检测获取连接时的有效性
      # 开启后会影响性能
      test-on-borrow: false
      # 检测归还连接时的有效性
      # 开启后会影响性能
      test-on-return: false
      # 是否开启PSCache,即是否缓存preparedStatement(提升写入、查询效率)
      # 建议在支持游标的数据库开启,例如:Oracle
      pool-prepared-statements: false
      # 每个连接上PSCache的最大值
      # 如果大于0,pool-prepared-statements自动开启
      max-pool-prepared-statement-per-connection-size: -1
      # 配置默认的监控统计拦截的Filter
      # 不配置则监控页面中的SQL无法统计
      # stat - SQL监控配置
      # wall - SQL防火墙配置
      # slf4j - Druid日志配置
      filters: stat,wall,slf4j
      # 配置过滤器
      filter:
        # SQL监控配置
        stat:
          enabled: true
          db-type: mysql
          # 是否开启慢SQL统计
          log-slow-sql: true
          # 慢SQL时间
          slow-sql-millis: 10000
          # 慢SQL日志级别
          slow-sql-log-level: ERROR
          # 是否开启合并SQL
          # 开启后,select * from table where id = 1 和 select * from table where id = 2 将合并为 select * from table where id = ?
          merge-sql: true
        # SQL防火墙配置
        wall:
          enabled: true
          config:
            # 允许新增
            insert-allow: true
            # 允许更新
            update-allow: true
            # 禁止更新时无条件
            update-where-none-check: true
            # 允许删除
            delete-allow: true
            # 禁止删除时无条件
            delete-where-none-check: true
            # 禁止对表ALTER
            alter-table-allow: false
            # 禁止对表DROP
            drop-table-allow: false
        # Druid日志配置
        slf4j:
          enabled: true
          # 关闭数据源日志
          data-source-log-enabled: false
          # 关闭连接日志
          connection-log-enabled: false
          # 开启执行SQL日志
          statement-executable-sql-log-enable: true
          # 开启结果映射日志
          result-set-log-enabled: true
      # 配置统计页面
      stat-view-servlet:
        enabled: true
        # 允许重置监控数据
        reset-enable: true
        # 访问白名单
        allow: 127.0.0.1
        # 访问黑名单
        deny: 192.168.0.100
        # 访问用户名
        login-username: druid
        # 访问密码
        login-password: 123456
      # 配置统计页面过滤
      web-stat-filter:
        enabled: true
        # 过滤路径
        url-pattern: /*
        # 排除路径
        exclusions: .js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*
        # 开启session统计
        session-stat-enable: true
        # session统计的最大个数
        session-stat-max-count: 100

# Mybatis-plus配置
mybatis-plus:
  mapper-locations: classpath:mapper/*.xml
  global-config:
    db-config:
      # 主键类型:自增
      id-type: AUTO
      # 表前缀
      table-prefix: t_
#  configuration:
#    # 打印sql,生产建议关闭
#    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  • 创建实体类
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;

/**
 * 用户
 *
 * @author CL
 */
@Data
@TableName(keepGlobalPrefix = true)
public class User extends Model<User> {

    @TableId
    private Long id;

    @TableField
    private String username;

    @TableField
    private String sex;

    @TableField
    private String phone;

}
  • 创建Mapper
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.c3stones.entity.User;
import org.apache.ibatis.annotations.Mapper;

/**
 * 用户 Mapper
 */
@Mapper
public interface UserMapper extends BaseMapper<User> {
}
  • 创建Controller
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.c3stones.entity.User;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 用户 Controller
 *
 * @author CL
 */
@RestController
@RequestMapping("/user")
public class UserController {

    /**
     * 根据ID查询
     *
     * @param id ID
     * @return 用户信息
     */
    @RequestMapping("/{id}")
    public User get(@PathVariable Long id) {
        return new User().selectById(id);
    }

    /**
     * 查询全部用户
     *
     * @return 用户列表
     */
    @RequestMapping("/list")
    public List<User> list() {
        return new User().selectAll();
    }

    /**
     * 更新用户
     *
     * @return 更新结果
     */
    @RequestMapping("/update")
    public Boolean update() {
        return new User().update(new LambdaUpdateWrapper<User>().set(User::getPhone, "123456789"));
    }

    /**
     * 删除用户
     *
     * @return 删除结果
     */
    @RequestMapping("/delete")
    public Boolean delete() {
        return new User().delete(new QueryWrapper<>());
    }

}
  • 创建启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * 启动类
 *
 * @author CL
 */
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

4. 测试

  • 测试访问权限

    • 非白名单访问: http://192.168.0.101:8080/druid
    • 白名单访问http://127.0.0.1:8080/druid
    • 输入错误的用户名/密码
    • 输入正确的用户名/密码
  • 验证SQL统计(SQL合并、慢SQL)

    • 访问根据ID查询用户接口
    curl http://127.0.0.1:8080/user/1

    • 访问查询所有用户接口

      为了测试慢SQL,需要给用户表多预置一些数据。

    curl http://127.0.0.1:8080/user/list


      后台日志打印:

    2023-02-26 20:13:20.197 ERROR 162564 --- [nio-8080-exec-1] c.alibaba.druid.filter.stat.StatFilter   : slow sql 19744 millis. SELECT  id,username,sex,phone  FROM t_user[]
  • 验证SQL防火墙

    • 验证更新时无WHERE条件
    http://127.0.0.1:8080/user/update

      接口报500错误,后台日志打印(update none condition not allow):

    2023-02-26 20:14:35.732 ERROR 73852 --- [nio-8080-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.apache.ibatis.exceptions.PersistenceException: 
    Error updating database.  Cause: java.sql.SQLException: sql injection violation, dbType mysql, druid-version 1.2.16, update none condition not allow : UPDATE t_user  SET phone=?
    
    ......
    • 验证删除时无WHERE条件
    curl http://127.0.0.1:8080/user/delete

      接口报500错误,后台日志打印(delete none condition not allow):

    2023-02-26 20:15:19.536 ERROR 73852 --- [nio-8080-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.apache.ibatis.exceptions.PersistenceException: 
    Error updating database.  Cause: java.sql.SQLException: sql injection violation, dbType mysql, druid-version 1.2.16, delete none condition not allow : DELETE FROM t_user
    
    ......

  • WEB应用

  • URL监控

5. 项目地址

  spring-boot-druid-demo

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/398285.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript中的数据类型以及存储上的差别?

前言 在JavaScript中&#xff0c;我们可以分成两种类型&#xff1a; 基本类型复杂类型 两种类型的区别是&#xff1a;存储位置不同 一、基本类型 基本类型主要为以下6种&#xff1a; NumberStringBooleanUndefinednullsymbol Number 数值最常见的整数类型格式则为十进制…

最强分布式锁工具:Redisson

1 Redisson概述1.1 什么是Redisson&#xff1f;Redisson是一个在Redis的基础上实现的Java驻内存数据网格&#xff08;In-Memory Data Grid&#xff09;。它不仅提供了一系列的分布式的Java常用对象&#xff0c;还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, Sorted…

学python的第六天---字符串

一、只出现一次的字符其他&#xff1a;round(XXX,1)忽略大小写比较字符串大小字符串几个可以使用的函数二、去掉多余的空格写法一&#xff1a;写法二&#xff1a;三、信息加密写法一&#xff1a;写法二:写法三&#xff1a;自己的写法四、单词替换五、倒排单词写法一&#xff1a…

面试官:什么是双亲委派模型?如何打破它?

本文已经收录进 JavaGuide(「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。) 参加过校招面试的同学,应该对这个问题不陌生。一般提问 JVM 知识点的时候,就会顺带问你双亲委派模型(别扭的翻译。。。)。 就算是不准备面试,学习双亲委派模型对于我…

if-else if与switch的练习1:输入两个数,输出两个数的加减乘除的值

1.if-else if的练习 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice…

所有科研人警惕,掠夺型期刊和劫持型期刊的区别,千万别投错了

当今&#xff0c;新形式的学术出版物——例如数字式或开源式的学术期刊日益普及&#xff0c;热门期刊的数量逐年增长【1】。 人们获取学术出版物也越来越容易&#xff0c;使得更多的科研人员&#xff08;特别是在低收入国家&#xff09;能够及时了解各自研究领域的最新发展态势…

ubuntu20.04搭建detectron2环境

Ubuntu22.04安装Cuda11.3 Linux下驱动安装 # 以下命令按顺序执行 sudo apt update && sudo apt upgrade -y # or sudo apt update # 查看显卡信息 ubuntu-drivers devices sudo ubuntu-drivers autoinstall # or sudo apt install nvidia-driver-510 reboot nvidia-s…

毕业设计 基于51单片机WIFI智能家居系统设计

基于51单片机WIFI智能家居系统设计1、毕业设计选题原则说明&#xff08;重点&#xff09;2、项目资料2.1 系统框架2.2 系统功能3、部分电路设计3.1 STC89C52单片机最小系统电路设计3.2 ESP8266 WIFI电路设计3.3 DHT11温湿度传感器电路设计4、部分代码展示4.1 LCD12864显示字符串…

JavaEE简单示例——Spring的入门程序

简单介绍&#xff1a; 在之前我们简单的介绍了有关于Spring的基础知识&#xff0c;那么现在我们就来一步步的把理论融入到实践中&#xff0c;开始使用这个框架&#xff0c;使用过程也是非常的简单&#xff0c;大致可以分为几个基础的步骤&#xff1a; 1.首先引入Spring的Mave…

TypeScript深度剖析:TypeScript 中泛型的理解?应用场景?

一、是什么 泛型程序设计&#xff08;generic programming&#xff09;是程序设计语言的一种风格或范式 泛型允许我们在强类型程序设计语言中编写代码时使用一些以后才指定的类型&#xff0c;在实例化时作为参数指明这些类型 在typescript中&#xff0c;定义函数&#xff0c;…

一文快速入门 HTML 网页基础

专栏简介: 前端从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 1.HTML 结构 1.1. 认识 HTML 标签 1.2 HTML 文件结构…

[MySQL核心]1.表操作

MySQL核心--表操作表操作一表操作二&#xff08;CRUD操作&#xff09;表操作一 创建表 比较规范的写法&#xff0c;关键字应该要大写&#xff0c;其他比如表名&#xff0c;字段这些自定义的可以小写 ENGINEINNODB DEFAULT CHARSETutf8 指定存储引擎以及默认的字符集&#xff0c…

04-CSS

一、其他样式 1、圆角边框在 CSS3 中&#xff0c;新增了圆角边框样式&#xff0c;这样我们的盒子就可以变圆角了。border-radius 属性用于设置元素的外边框圆角。语法&#xff1a;border-radius:length;参数值可以为数值或百分比的形式如果是正方形&#xff0c;想要设置为一个圆…

IBM ILOG CPLEX Optimization Studio 22.1 Crack

BM ILOG CPLEX 优化工作室 建立和解决复杂的优化模型以确定最佳行动 通过数据科学改变您的业务决策 IBM ILOG CPLEX Optimization Studio 使用决策优化技术来优化您的业务决策&#xff0c;快速开发和部署优化模型&#xff0c;并创建可显着改善业务成果的真实应用程序。 如何&…

ROS 摄像头的使用

参考&#xff1a; ​ youtubeArticulated Robotics ​ 作者Josh Newans博客 建议&#xff1a; 这个只是我的看法&#xff0c;强烈建议看原视频或博客 png&#xff1a;无损压缩 jpeg&#xff1a;有损压缩 Driver Node 负责连接硬件设备&#xff0c;读取摄像头数据"ima…

Learning C++ No.13【STL No.3】

引言&#xff1a; 北京时间&#xff1a;2023/3/7/15:33&#xff0c;还有27分钟就要去上课啦&#xff01;刚刚把最近因为考试原因欠的课给还干净了&#xff0c;已经准备好今天晚上接受航哥的毒打了&#xff0c;毒打就毒打&#xff0c;咱不怕&#xff0c;只要不欠钱&#xff0c;…

小黑子—Java从入门到入土过程:第一章

Java零基础入门1.0Java系列第一章1. cmd2. 利用cmd打开qq并配置环境变量3. Java概述和学习方法4. JDK下载和安装5. hello world 小案例6. bug常见小问题7. 环境变量8. Notepad9. java 语言的发展10. java 能干什么10.1 javaSE10.2 javaME10.3 javaEE11. java为什么火12. java为…

什么是激励能力?HR人才测评

什么是激励能力&#xff1f;激励能力主要是针对管理型岗位而言的&#xff0c;尤其是团队型管理&#xff0c;既要督导团队成员&#xff0c;更需要掌握激励下属的方法和技巧。在HR人才测评系统中&#xff0c;对于管理型岗位的人才测评指标&#xff0c;通常也会包含激励能力&#…

蓝牙耳机哪款佩戴舒服?2023佩戴最舒适蓝牙耳机

由于每天坐在电脑桌前的时间比较长&#xff0c;需要音乐和运动调剂一下自己&#xff0c;而说到与蓝牙耳机&#xff0c;大家更加关注的是音质和佩戴舒适度吧&#xff0c;作为一位音乐发烧友&#xff0c;使用过的耳机数不胜数&#xff0c;接下来跟大家分享一下我的体验感受。 第…

关于供应链,一文教你全面了解什么是供应链

什么是供应链&#xff1f;供应链是指产品生产和流通过程中所涉及的原材料供应商、生产商、分销商、零售商以及最终消费者等成员通过与上游、下游成员的连接 (linkage) 组成的网络结构。也即是由物料获取、物料加工、并将成品送到用户手中这一过程所涉及的企业和企业部门组成的一…