全方位监控、防SQL注入攻击等
添加druid连接池的依赖,如下所示:
com.alibaba druid1.2.15
说明如下:
package com.hh.springboottest.config; import com.alibaba.druid.pool.DruidDataSource; import com.alibaba.druid.support.http.StatViewServlet; import com.alibaba.druid.support.http.WebStatFilter; 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 javax.sql.DataSource; import java.sql.SQLException; import java.util.Arrays; @Configuration public class MyDataSourceConfig { // 将application.properties中spring.datasource前缀对应的值赋值给DataSource类属性 @ConfigurationProperties(prefix = "spring.datasource") @Bean public DataSource dataSource() { DruidDataSource druidDataSource = new DruidDataSource(); try { // 开启SQL监控菜单功能,让druid进行SQL的执行统计 // 开启SQL防火墙菜单功能 druidDataSource.setFilters("stat,wall"); } catch (SQLException e) { e.printStackTrace(); } return druidDataSource; } // 向IOC容器添加ServletRegistrationBean组件,开启druid监控功能 @Bean public ServletRegistrationBean statViewServlet() { StatViewServlet statViewServlet = new StatViewServlet(); ServletRegistrationBeanservletRegistrationBean = // druid监控的访问页面是/druid/* new ServletRegistrationBean<>(statViewServlet, "/druid/*"); // 开启监控页面的访问登录账号和密码 servletRegistrationBean.addInitParameter("loginUsername", "druid"); servletRegistrationBean.addInitParameter("loginPassword", "123456"); return servletRegistrationBean; } // 开启Web应用菜单功能,让druid进行Web应用的统计 @Bean public FilterRegistrationBean webStatFilter() { WebStatFilter webStatFilter = new WebStatFilter(); FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean<>(webStatFilter); // 设置统计的Web URL filterRegistrationBean.setUrlPatterns(Arrays.asList("/*")); // 设置排除的Web URL filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return filterRegistrationBean; } }
在代码中可以对DataSource进行各种配置参数的set,也可以在application.properties中对durid连接池进行配置,如下所示:
# 最好注释HikariDataSource # spring.datasource.type=com.zaxxer.hikari.HikariDataSource spring.datasource.filters=stat,wall spring.datasource.max-active=12
package com.hh.springboottest.myController; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import javax.sql.DataSource; @Slf4j @RestController public class HelloController { @Autowired private JdbcTemplate jdbcTemplate; @Autowired DataSource dataSource; @ResponseBody @GetMapping("/queryFromDb") public String queryFromDb() { Long userCount = jdbcTemplate.queryForObject("select count(*) from user", Long.class); // 返回的结果是:数据库连接池类型为class com.alibaba.druid.pool.DruidDataSource log.info("数据库连接池类型为{}", dataSource.getClass()); return userCount.toString(); } }
访问http://localhost:8080/druid/index.html,页面效果如下:
其中数据源菜单在RestController等进行了调用才有结果显示
其中SQL监控页面如下。
SQL监控项上,执行时间、读取行数、更新行数都有区间分布,将耗时分布成8个区间:
耗时区间分布提供了“执行+RS时分布”,是将执行时间+ResultSet持有时间合并监控,这个能方便诊断返回行数过多的查询
首先注释上面MyDataSourceConfig的@Configuration注解,或者删除MyDataSourceConfig.java文件。开始进行starter版的开发
添加druid-spring-boot-starter的依赖;和添加spring-boot-starter-aop,用于druid监控页的Spring监控菜单。如下所示:
com.alibaba druid-spring-boot-starter1.2.15 org.springframework.boot spring-boot-starter-aop
可以看到自动添加了druid、spring-boot-autoconfiguration依赖
查看druid-spring-boot-starter-1.2.15.jar的DruidDataSourceAutoConfigure.class,可以看到:
package com.alibaba.druid.spring.boot.autoconfigure; ......省略部分...... @Configuration @ConditionalOnClass({DruidDataSource.class}) @AutoConfigureBefore({DataSourceAutoConfiguration.class}) @EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class}) @Import({DruidSpringAopConfiguration.class, DruidStatViewServletConfiguration.class, DruidWebStatFilterConfiguration.class, DruidFilterConfiguration.class}) public class DruidDataSourceAutoConfigure { ......省略部分...... @Bean( initMethod = "init" ) @ConditionalOnMissingBean public DataSource dataSource() { LOGGER.info("Init DruidDataSource"); return new DruidDataSourceWrapper(); } }
查看DruidStatProperties配置类,druid的配置是由spring.datasource.druid开头的参数进行配置的
......省略部分...... @ConfigurationProperties("spring.datasource.druid") public class DruidStatProperties { ......省略部分...... }
查看DataSourceProperties配置类,datasource的配置是由spring.datasource开头的参数进行配置的
......省略部分...... @ConfigurationProperties( prefix = "spring.datasource" ) public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean { ......省略部分...... }
查看DruidSpringAopConfiguration类,aop相关的是由spring.datasource.druid.aop-patterns参数进行配置的,主要用来监控SpringBean。对应druid监控页面的Spring监控菜单
......省略部分...... @ConditionalOnProperty({"spring.datasource.druid.aop-patterns"}) public class DruidSpringAopConfiguration { ......省略部分...... }
查看DruidStatViewServletConfiguration类,如下所示:
......省略部分...... @ConditionalOnWebApplication @ConditionalOnProperty( name = {"spring.datasource.druid.stat-view-servlet.enabled"}, havingValue = "true" ) public class DruidStatViewServletConfiguration { private static final String DEFAULT_ALLOW_IP = "127.0.0.1"; public DruidStatViewServletConfiguration() { } @Bean public ServletRegistrationBean statViewServletRegistrationBean(DruidStatProperties properties) { DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); ServletRegistrationBean registrationBean = new ServletRegistrationBean(); registrationBean.setServlet(new StatViewServlet()); registrationBean.addUrlMappings(new String[]{config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"}); if (config.getAllow() != null) { registrationBean.addInitParameter("allow", config.getAllow()); } else { registrationBean.addInitParameter("allow", "127.0.0.1"); } if (config.getDeny() != null) { registrationBean.addInitParameter("deny", config.getDeny()); } if (config.getLoginUsername() != null) { registrationBean.addInitParameter("loginUsername", config.getLoginUsername()); } if (config.getLoginPassword() != null) { registrationBean.addInitParameter("loginPassword", config.getLoginPassword()); } if (config.getResetEnable() != null) { registrationBean.addInitParameter("resetEnable", config.getResetEnable()); } return registrationBean; } }
查看DruidWebStatFilterConfiguration类,如下所示:
......省略部分...... @ConditionalOnWebApplication @ConditionalOnProperty( name = {"spring.datasource.druid.web-stat-filter.enabled"}, havingValue = "true" ) public class DruidWebStatFilterConfiguration { public DruidWebStatFilterConfiguration() { } @Bean public FilterRegistrationBean webStatFilterRegistrationBean(DruidStatProperties properties) { DruidStatProperties.WebStatFilter config = properties.getWebStatFilter(); FilterRegistrationBean registrationBean = new FilterRegistrationBean(); WebStatFilter filter = new WebStatFilter(); registrationBean.setFilter(filter); registrationBean.addUrlPatterns(new String[]{config.getUrlPattern() != null ? config.getUrlPattern() : "/*"}); registrationBean.addInitParameter("exclusions", config.getExclusions() != null ? config.getExclusions() : "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); ......省略部分...... } ......省略部分...... }
查看DruidFilterConfiguration类,是对所有Druid自己的Filter的配置,比如wall防火墙
......省略部分...... public class DruidFilterConfiguration { private static final String FILTER_STAT_PREFIX = "spring.datasource.druid.filter.stat"; private static final String FILTER_CONFIG_PREFIX = "spring.datasource.druid.filter.config"; private static final String FILTER_ENCODING_PREFIX = "spring.datasource.druid.filter.encoding"; private static final String FILTER_SLF4J_PREFIX = "spring.datasource.druid.filter.slf4j"; private static final String FILTER_LOG4J_PREFIX = "spring.datasource.druid.filter.log4j"; private static final String FILTER_LOG4J2_PREFIX = "spring.datasource.druid.filter.log4j2"; private static final String FILTER_COMMONS_LOG_PREFIX = "spring.datasource.druid.filter.commons-log"; private static final String FILTER_WALL_PREFIX = "spring.datasource.druid.filter.wall"; private static final String FILTER_WALL_CONFIG_PREFIX = "spring.datasource.druid.filter.wall.config"; ......省略部分...... }
druid的配置如下所示:
# 配置druid监控功能 spring.datasource.druid.stat-view-servlet.enabled=true spring.datasource.druid.stat-view-servlet.login-username=druid spring.datasource.druid.stat-view-servlet.login-password=123456 spring.datasource.druid.stat-view-servlet.reset-enable=false # 开启druid监控页面的sql监控菜单、防火墙菜单 spring.datasource.druid.filters=stat,wall,slf4j # 对filters里面的stat的详细配置 spring.datasource.druid.filter.stat.enabled=true spring.datasource.druid.filter.stat.log-slow-sql=true # 1秒 spring.datasource.druid.filter.stat.slow-sql-millis=1000 # 对filters里面的wall的详细配置 spring.datasource.druid.filter.wall.enabled=true spring.datasource.druid.filter.wall.config.update-allow=true spring.datasource.druid.filter.wall.config.drop-table-allow=false # 配置Web应用菜单功能 spring.datasource.druid.web-stat-filter.enabled=true spring.datasource.druid.web-stat-filter.url-pattern=/* spring.datasource.druid.web-stat-filter.exclusions=*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* # 监控指定路径下的SpringBean。用于Spring监控菜单 spring.datasource.druid.aop-patterns=com.hh.springboottest.*
连接池配置
spring.datasource.druid.initial-size= spring.datasource.druid.max-active= spring.datasource.druid.min-idle= spring.datasource.druid.max-wait= spring.datasource.druid.pool-prepared-statements= spring.datasource.druid.max-pool-prepared-statement-per-connection-size= # 和上面的等价 spring.datasource.druid.max-open-prepared-statements= spring.datasource.druid.validation-query= spring.datasource.druid.validation-query-timeout= spring.datasource.druid.test-on-borrow= spring.datasource.druid.test-on-return= spring.datasource.druid.test-while-idle= spring.datasource.druid.time-between-eviction-runs-millis= spring.datasource.druid.min-evictable-idle-time-millis= spring.datasource.druid.max-evictable-idle-time-millis= # 配置多个英文逗号分隔 spring.datasource.druid.filters=
监控配置
# WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter # 是否启用StatFilter,默认值false spring.datasource.druid.web-stat-filter.enabled= 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 Wiki,配置_StatViewServlet配置 # 是否启用StatViewServlet(监控页面),默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全) spring.datasource.druid.stat-view-servlet.enabled= 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监控AOP切入点,如x.y.z.service.*, 配置多个英文逗号分隔 spring.datasource.druid.aop-patterns=