SpringBoot integrates Druid data source

SpringBoot integrates Druid data source

Preconditions

SpringBoot integrates MyBatis framework

Add dependency

<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> Copy code

Add configuration

  • application.yml
# Tomcat server: port: 8088 # DataSource spring: datasource: name: druidDataSource type: com.alibaba.druid.pool.DruidDataSource druid: driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/tmall?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true&characterEncoding=utf-8 username: root password: 123456 filters: stat,wall,log4j,config max-active: 100 initial-size: 1 max-wait: 60000 min-idle: 1 time-between-eviction-runs-millis: 60000 min-evictable-idle-time-millis: 300000 validation-query: select'x' test-while-idle: true test-on-borrow: false test-on-return: false pool-prepared-statements: true max-open-prepared-statements: 50 max-pool-prepared-statement-per-connection-size: 20 Copy code
  • DruidDataSourceProperties.java
package com.gold.tmall.config; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author zhang.fuiqng * @date 2021-04-24 14:47:00 */ @ConfigurationProperties(prefix = "spring.datasource.druid") public class DruidDataSourceProperties { /** * Driver class name * mysql: com.mysql.cj.jdbc.Driver (MySQL 8.0 and above) * oracle: oracle.jdbc.driver.OracleDriver */ private String driverClassName; /** * Database connection address */ private String url; /** * database username */ private String username; /** * Database password */ private String password; /** * The number of physical connections established during initialization. Initialization occurs when the init method is called, or the first time getConnection */ private int initialSize; /** * Minimum number of connection pools */ private int minIdle; /** * Maximum number of connection pools */ private int maxActive = 100; /** * The maximum waiting time when getting a connection, in milliseconds. After maxWait is configured, fair lock is enabled by default, and the concurrency efficiency will decrease. * If necessary, you can use unfair locks by configuring the useUnfairLock attribute to true. */ private long maxWait; /** * Has two meanings: * 1) The Destroy thread will detect the connection interval, and if the connection idle time is greater than or equal to minEvictableIdleTimeMillis, the physical connection will be closed. * 2) The judgment basis of testWhileIdle, please refer to the description of testWhileIdle property in detail */ private long timeBetweenEvictionRunsMillis; /** * The minimum time the connection remains idle without being evicted */ private long minEvictableIdleTimeMillis; /** * The sql used to check whether the connection is valid, the requirement is a query statement, usually select'x'. * If validationQuery is null, testOnBorrow, testOnReturn, testWhileIdle will not work. */ private String validationQuery; /** * It is recommended to configure to true, which will not affect performance and ensure safety. * Check when applying for a connection. If the idle time is greater than timeBetweenEvictionRunsMillis, execute validationQuery to check whether the connection is valid. */ private boolean testWhileIdle; /** * Execute validationQuery to check whether the connection is valid when applying for a connection. This configuration will reduce performance. */ private boolean testOnBorrow; /** * Execute validationQuery to check whether the connection is valid when returning the connection. This configuration will reduce performance. */ private boolean testOnReturn; /** * Whether to cache preparedStatement, which is PSCache. PSCache greatly improves the performance of databases that support cursors, such as Oracle. It is recommended to close it under mysql. */ private boolean poolPreparedStatements; /** * To enable PSCache, it must be configured to be greater than 0. When it is greater than 0, poolPreparedStatements is automatically triggered and changed to true. * In Druid, there is no problem that PSCache under Oracle occupies too much memory. You can configure this value to be larger, for example, 100 */ private int maxPoolPreparedStatementPerConnectionSize; /** * The attribute type is a string. The extension plug-ins are configured by aliases. Commonly used plug-ins are: * Filter:stat for monitoring statistics * Log filter: log4j * Filter:wall to defend against SQL injection */ private String filters; public int getInitialSize() { return initialSize; } public void setInitialSize(int initialSize) { this.initialSize = initialSize; } public int getMinIdle() { return minIdle; } public void setMinIdle(int minIdle) { this.minIdle = minIdle; } public int getMaxActive() { return maxActive; } public void setMaxActive(int maxActive) { this.maxActive = maxActive; } public long getMaxWait() { return maxWait; } public void setMaxWait(long maxWait) { this.maxWait = maxWait; } public long getTimeBetweenEvictionRunsMillis() { return timeBetweenEvictionRunsMillis; } public void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) { this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; } public long getMinEvictableIdleTimeMillis() { return minEvictableIdleTimeMillis; } public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } public String getValidationQuery() { return validationQuery; } public void setValidationQuery(String validationQuery) { this.validationQuery = validationQuery; } public boolean isTestWhileIdle() { return testWhileIdle; } public void setTestWhileIdle(boolean testWhileIdle) { this.testWhileIdle = testWhileIdle; } public boolean isTestOnBorrow() { return testOnBorrow; } public void setTestOnBorrow(boolean testOnBorrow) { this.testOnBorrow = testOnBorrow; } public boolean isTestOnReturn() { return testOnReturn; } public void setTestOnReturn(boolean testOnReturn) { this.testOnReturn = testOnReturn; } public boolean isPoolPreparedStatements() { return poolPreparedStatements; } public void setPoolPreparedStatements(boolean poolPreparedStatements) { this.poolPreparedStatements = poolPreparedStatements; } public int getMaxPoolPreparedStatementPerConnectionSize() { return maxPoolPreparedStatementPerConnectionSize; } public void setMaxPoolPreparedStatementPerConnectionSize(int maxPoolPreparedStatementPerConnectionSize) { this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize; } public String getFilters() { return filters; } public void setFilters(String filters) { this.filters = filters; } public String getDriverClassName() { return driverClassName; } public void setDriverClassName(String driverClassName) { this.driverClassName = driverClassName; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } Copy code
  • DruidConfig.java
package com.gold.tmall.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.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.properties.EnableConfigurationProperties; 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.annotation.Resource; import javax.servlet.Filter; import javax.servlet.Servlet; import javax.sql.DataSource; import java.sql.SQLException; /** * EnableConfigurationProperties({DruidDataSourceProperties.class}) is used to import the configuration information of DruidDataSourceProperties in the previous step * @author zhang.fuiqng * @date 2021-04-24 14:59:00 */ @Configuration @EnableConfigurationProperties({DruidDataSourceProperties.class}) public class DruidConfig { @Resource private DruidDataSourceProperties properties; @Bean @ConditionalOnMissingBean public DataSource druidDataSource() { DruidDataSource druidDataSource = new DruidDataSource(); druidDataSource.setDriverClassName(properties.getDriverClassName()); druidDataSource.setUrl(properties.getUrl()); druidDataSource.setUsername(properties.getUsername()); druidDataSource.setPassword(properties.getPassword()); druidDataSource.setInitialSize(properties.getInitialSize()); druidDataSource.setMinIdle(properties.getMinIdle()); druidDataSource.setMaxActive(properties.getMaxActive()); druidDataSource.setMaxWait(properties.getMaxWait()); druidDataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis()); druidDataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis()); druidDataSource.setValidationQuery(properties.getValidationQuery()); druidDataSource.setTestWhileIdle(properties.isTestWhileIdle()); druidDataSource.setTestOnBorrow(properties.isTestOnBorrow()); druidDataSource.setTestOnReturn(properties.isTestOnReturn()); druidDataSource.setPoolPreparedStatements(properties.isPoolPreparedStatements()); druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(properties.getMaxPoolPreparedStatementPerConnectionSize()); try { druidDataSource.setFilters(properties.getFilters()); druidDataSource.init(); } catch (SQLException e) { e.printStackTrace(); } return druidDataSource; } /** * Register Servlet information, configure monitoring view * public ServletRegistrationBean druidServlet() is equivalent to Web Servlet configuration * @return Servlet registration information */ @Bean @ConditionalOnMissingBean public ServletRegistrationBean<Servlet> druidServlet() { ServletRegistrationBean<Servlet> servletRegistrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); //whitelist servletRegistrationBean.addInitParameter("allow","127.0.0.1"); //IP blacklist (when there is a common, deny takes precedence over allow): If deny is met, prompt: Sorry, you are not permitted to view this page. servletRegistrationBean.addInitParameter("deny","127.0.0.1"); //The account password for logging in to view information, used to log in to the Druid monitoring background servletRegistrationBean.addInitParameter("loginUsername", "admin"); servletRegistrationBean.addInitParameter("loginPassword", "admin"); //Is it possible to reset the data servletRegistrationBean.addInitParameter("resetEnable", "true"); return servletRegistrationBean; } /** * Register Filter information, monitor the interceptor * public FilterRegistrationBean filterRegistrationBean() is equivalent to Web Filter configuration * @return Filter registration information */ @Bean @ConditionalOnMissingBean public FilterRegistrationBean<Filter> filterRegistrationBean() { FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(); filterRegistrationBean.setFilter(new WebStatFilter()); filterRegistrationBean.addUrlPatterns("/*"); filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); return filterRegistrationBean; } } Copy code

Startup problem

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name'mybatisConfig': Unsatisfied dependency expressed through field'dataSource'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name'druidDataSource' defined in class path resource [com/louis/kitty/boot/config/DruidConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method'druidDataSource' threw exception; nested exception is java.lang.NoClassDefFoundError: org/apache/log4j/Priority at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:586) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:91) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:372) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1341) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:572) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759) ~[spring-beans-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.8.RELEASE.jar:5.0.8.RELEASE] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:398) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1258) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1246) [spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE] at com.louis.kitty.boot.KittyApplication.main(KittyApplication.java:10) [classes/:na] ... Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Priority at java.net.URLClassLoader.findClass(URLClassLoader.java:381) ~[na:1.8.0_131] at java.lang.ClassLoader.loadClass(ClassLoader. java:424) ~[na:1.8.0_131] at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) ~[na:1.8.0_131] at java.lang.ClassLoader.loadClass(ClassLoader.java: 357) ~[na:1.8.0_131] ... 49 common frames omitted Copy code
  • Add dependency
<!-- log4j --> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> Copy code
  • Configure log4j

Add the log4j.properties file under the src/main/resources path

### set log levels ### log4j.rootLogger = INFO, console, infoFile, errorFile LocationInfo=true log4j.appender.console = org.apache.log4j.ConsoleAppender log4j.appender.console.Target = System.out log4j.appender.console.layout = org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern =[%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%p]:%m %x %n log4j.appender.infoFile = org.apache.log4j.DailyRollingFileAppender log4j.appender.infoFile.Threshold = INFO log4j.appender.infoFile.File = D:/logs/log log4j.appender.infoFile.DatePattern ='.'yyyy-MM-dd'.log' log4j.appender.infoFile.Append=true log4j.appender.infoFile.layout = org.apache.log4j.PatternLayout log4j.appender.infoFile.layout.ConversionPattern =[%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%p]:%m %x %n log4j.appender.errorFile = org.apache.log4j.DailyRollingFileAppender log4j.appender.errorFile.Threshold = ERROR log4j.appender.errorFile.File = D:/logs/error log4j.appender.errorFile.DatePattern ='.'yyyy-MM-dd'.log' log4j.appender.errorFile.Append=true log4j.appender.errorFile.layout = org.apache.log4j.PatternLayout log4j.appender.errorFile.layout.ConversionPattern =[%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%p]:%m %x %n #log4j.appender.debugfile = org.apache.log4j.DailyRollingFileAppender #log4j.appender.debugfile.Threshold = DEBUG #log4j.appender.debugfile.File = D:/logs/debug #log4j.appender.debugfile.DatePattern ='.'yyyy-MM-dd'.log' #log4j.appender.debugfile.Append=true #log4j.appender.debugfile.layout = org.apache.log4j.PatternLayout #log4j.appender.debugfile.layout.ConversionPattern =[%d{yyyy-MM-dd HH:mm:ss,SSS}]-[%p]:%m %x %n Copy code

View monitoring

Source download

gitee.com/zhang_fuqin...