update > optimize code no longer use relaxed binding & fix for issue #1796 & optimize detail see issue #1813

This commit is contained in:
lihengming
2017-07-05 15:52:22 +08:00
parent ffa7e60da0
commit ca13e8ff5a
4 changed files with 363 additions and 60 deletions
@@ -18,7 +18,6 @@ package com.alibaba.druid.spring.boot.autoconfigure;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -33,15 +32,16 @@ import java.sql.SQLException;
*/
@Configuration
@ConditionalOnClass(com.alibaba.druid.pool.DruidDataSource.class)
@EnableConfigurationProperties(DruidStatProperties.class)
@EnableConfigurationProperties({DruidStatProperties.class, DruidDataSourceProperties.class})
@Import({DruidSpringAopConfiguration.class, DruidStatViewServletConfiguration.class, DruidWebStatFilterConfiguration.class})
public class DruidDataSourceAutoConfigure {
@Bean
@ConfigurationProperties("spring.datasource.druid")
@ConditionalOnMissingBean
public DataSource dataSource(Environment env) {
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
public DataSource dataSource(DruidDataSourceProperties properties, Environment env) {
DruidDataSource dataSource = DruidDataSourceBuilder
.create()
.build(properties);
//if not found prefix 'spring.datasource.druid' settings,'spring.datasource' prefix settings will be used.
if (dataSource.getUsername() == null) {
@@ -17,46 +17,129 @@ package com.alibaba.druid.spring.boot.autoconfigure;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.core.env.Environment;
import java.util.HashMap;
import java.util.Map;
import java.sql.SQLException;
/**
* @author lihengming [89921218@qq.com]
*/
public class DruidDataSourceBuilder {
private Map<String, String> properties = new HashMap<String, String>();
public static DruidDataSourceBuilder create() {
return new DruidDataSourceBuilder();
}
@Deprecated
public DruidDataSource build() {
return new DruidDataSource();
}
/**
* Use Spring Environment by specify configuration properties prefix to build DruidDataSource.
* <p>
* Environment support .properties, .yml ,command etc.
* <p>
* Properties key style support max-active,MAX_ACTIVE,maxActive etc.
* <p>
* Please read the spring documents for details.
* @param env Spring Environment
* @param prefix Spring Boot configuration properties prefix
* @return DruidDataSource
*/
public DruidDataSource build(Environment env, String prefix) {
DruidDataSourceProperties properties = new DruidDataSourceProperties();
properties.setUrl(env.getProperty(prefix + "url"));
properties.setUsername(env.getProperty(prefix + "username"));
properties.setPassword(env.getProperty(prefix + "password"));
properties.setDriverClassName(env.getProperty(prefix + "driver-class-name"));
properties.setInitialSize(env.getProperty(prefix + "initial-size", Integer.class));
properties.setMaxActive(env.getProperty(prefix + "max-active", Integer.class));
properties.setMinIdle(env.getProperty(prefix + "min-idle", Integer.class));
properties.setMaxWait(env.getProperty(prefix + "max-wait", Long.class));
properties.setPoolPreparedStatements(env.getProperty(prefix + "pool-prepared-statements", Boolean.class));
properties.setMaxOpenPreparedStatements(env.getProperty(prefix + "max-open-prepared-statements", Integer.class));
properties.setMaxPoolPreparedStatementPerConnectionSize(
env.getProperty(prefix + "max-pool-prepared-statement-per-connection-size", Integer.class));
properties.setValidationQuery(env.getProperty(prefix + "validation-query"));
properties.setValidationQueryTimeout(env.getProperty(prefix + "validation-query-timeout", Integer.class));
properties.setTestOnBorrow(env.getProperty(prefix + "test-on-borrow", Boolean.class));
properties.setTestOnReturn(env.getProperty(prefix + "test-on-return", Boolean.class));
properties.setTestWhileIdle(env.getProperty(prefix + "test-while-idle", Boolean.class));
properties.setTimeBetweenEvictionRunsMillis(env.getProperty(prefix + "time-between-eviction-runs-millis", Long.class));
properties.setMinEvictableIdleTimeMillis(env.getProperty(prefix + "min-evictable-idle-time-millis", Long.class));
properties.setMaxEvictableIdleTimeMillis(env.getProperty(prefix + "max-evictable-idle-time-millis", Long.class));
properties.setFilters(env.getProperty(prefix + "filters"));
return build(properties);
}
DruidDataSource build(DruidDataSourceProperties properties) {
DruidDataSource dataSource = new DruidDataSource();
maybeGetDriverClassName();
bind(dataSource);
if (properties.getUrl() != null) {
dataSource.setUrl(properties.getUrl());
}
if (properties.getUsername() != null) {
dataSource.setUsername(properties.getUsername());
}
if (properties.getPassword() != null) {
dataSource.setPassword(properties.getPassword());
}
if (properties.getDriverClassName() != null) {
dataSource.setDriverClassName(properties.getDriverClassName());
}
if (properties.getInitialSize() != null) {
dataSource.setInitialSize(properties.getInitialSize());
}
if (properties.getMaxActive() != null) {
dataSource.setMaxActive(properties.getMaxActive());
}
if (properties.getMinIdle() != null) {
dataSource.setMinIdle(properties.getMinIdle());
}
if (properties.getMaxWait() != null) {
dataSource.setMaxWait(properties.getMaxWait());
}
if (properties.getPoolPreparedStatements() != null) {
dataSource.setPoolPreparedStatements(properties.getPoolPreparedStatements());
}
if (properties.getMaxOpenPreparedStatements() != null) {
dataSource.setMaxOpenPreparedStatements(properties.getMaxOpenPreparedStatements());
}
if (properties.getMaxPoolPreparedStatementPerConnectionSize() != null) {
dataSource.setMaxPoolPreparedStatementPerConnectionSize(properties.getMaxPoolPreparedStatementPerConnectionSize());
}
if (properties.getValidationQuery() != null) {
dataSource.setValidationQuery(properties.getValidationQuery());
}
if (properties.getValidationQueryTimeout() != null) {
dataSource.setValidationQueryTimeout(properties.getValidationQueryTimeout());
}
if (properties.getTestWhileIdle() != null) {
dataSource.setTestWhileIdle(properties.getTestWhileIdle());
}
if (properties.getTestOnBorrow() != null) {
dataSource.setTestOnBorrow(properties.getTestOnBorrow());
}
if (properties.getTestOnReturn() != null) {
dataSource.setTestOnReturn(properties.getTestOnReturn());
}
if (properties.getTimeBetweenEvictionRunsMillis() != null) {
dataSource.setTimeBetweenEvictionRunsMillis(properties.getTimeBetweenEvictionRunsMillis());
}
if (properties.getMinEvictableIdleTimeMillis() != null) {
dataSource.setMinEvictableIdleTimeMillis(properties.getMinEvictableIdleTimeMillis());
}
if (properties.getMaxEvictableIdleTimeMillis() != null) {
dataSource.setMaxEvictableIdleTimeMillis(properties.getMaxEvictableIdleTimeMillis());
}
try {
if (properties.getFilters() != null) {
dataSource.setFilters(properties.getFilters());
}
} catch (SQLException e) {
e.printStackTrace();
}
return dataSource;
}
//use spring boot relaxed binding by reflection config druid . detail see Spring Boot Reference Relaxed binding section.
private void bind(DruidDataSource result) {
MutablePropertyValues properties = new MutablePropertyValues(this.properties);
new RelaxedDataBinder(result)
.withAlias("url", "jdbcUrl")
.withAlias("username", "user")
.bind(properties);
}
private void maybeGetDriverClassName() {
if (!this.properties.containsKey("driverClassName")
&& this.properties.containsKey("url")) {
String url = this.properties.get("url");
String driverClass = DatabaseDriver.fromJdbcUrl(url).getDriverClassName();
this.properties.put("driverClassName", driverClass);
}
}
}
@@ -0,0 +1,219 @@
package com.alibaba.druid.spring.boot.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* @author lihengming [89921218@qq.com]
*/
@ConfigurationProperties("spring.datasource.druid")
public class DruidDataSourceProperties {
private String url;
private String username;
private String password;
private String driverClassName;
private Integer initialSize;
private Integer maxActive;
private Integer minIdle;
private Long maxWait;
private Boolean poolPreparedStatements;
private Integer maxOpenPreparedStatements;
private Integer maxPoolPreparedStatementPerConnectionSize;
private String validationQuery;
private Integer validationQueryTimeout;
private Boolean testOnBorrow;
private Boolean testOnReturn;
private Boolean testWhileIdle;
private Long timeBetweenEvictionRunsMillis;
private Long minEvictableIdleTimeMillis;
private Long maxEvictableIdleTimeMillis;
private String filters;
private String proxyFilters;
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;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
public Integer getInitialSize() {
return initialSize;
}
public void setInitialSize(Integer initialSize) {
this.initialSize = initialSize;
}
public Integer getMaxActive() {
return maxActive;
}
public void setMaxActive(Integer maxActive) {
this.maxActive = maxActive;
}
public Integer getMinIdle() {
return minIdle;
}
public void setMinIdle(Integer minIdle) {
this.minIdle = minIdle;
}
public Long getMaxWait() {
return maxWait;
}
public void setMaxWait(Long maxWait) {
this.maxWait = maxWait;
}
public Boolean getPoolPreparedStatements() {
return poolPreparedStatements;
}
public void setPoolPreparedStatements(Boolean poolPreparedStatements) {
this.poolPreparedStatements = poolPreparedStatements;
}
public Integer getMaxOpenPreparedStatements() {
return maxOpenPreparedStatements;
}
public void setMaxOpenPreparedStatements(Integer maxOpenPreparedStatements) {
this.maxOpenPreparedStatements = maxOpenPreparedStatements;
}
public Integer getMaxPoolPreparedStatementPerConnectionSize() {
return maxPoolPreparedStatementPerConnectionSize;
}
public void setMaxPoolPreparedStatementPerConnectionSize(Integer maxPoolPreparedStatementPerConnectionSize) {
this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;
}
public String getValidationQuery() {
return validationQuery;
}
public void setValidationQuery(String validationQuery) {
this.validationQuery = validationQuery;
}
public Integer getValidationQueryTimeout() {
return validationQueryTimeout;
}
public void setValidationQueryTimeout(Integer validationQueryTimeout) {
this.validationQueryTimeout = validationQueryTimeout;
}
public Boolean getTestOnBorrow() {
return testOnBorrow;
}
public void setTestOnBorrow(Boolean testOnBorrow) {
this.testOnBorrow = testOnBorrow;
}
public Boolean getTestOnReturn() {
return testOnReturn;
}
public void setTestOnReturn(Boolean testOnReturn) {
this.testOnReturn = testOnReturn;
}
public Boolean getTestWhileIdle() {
return testWhileIdle;
}
public void setTestWhileIdle(Boolean testWhileIdle) {
this.testWhileIdle = testWhileIdle;
}
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 Long getMaxEvictableIdleTimeMillis() {
return maxEvictableIdleTimeMillis;
}
public void setMaxEvictableIdleTimeMillis(Long maxEvictableIdleTimeMillis) {
this.maxEvictableIdleTimeMillis = maxEvictableIdleTimeMillis;
}
public String getFilters() {
return filters;
}
public void setFilters(String filters) {
this.filters = filters;
}
public String getProxyFilters() {
return proxyFilters;
}
public void setProxyFilters(String proxyFilters) {
this.proxyFilters = proxyFilters;
}
}
@@ -15,14 +15,12 @@
*/
package com.alibaba.druid.spring.boot;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import org.junit.Test;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import javax.sql.DataSource;
@@ -50,47 +48,50 @@ public class DruidDataSourceTestCase {
public void testDataSourcePropertiesOverridden() throws Exception {
this.context.register(DruidDataSourceConfiguration.class);
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "url=jdbc:h2:file:./demo-db");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "initial-size=2");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "max-active=30");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "min-idle=2");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "max-wait=1234");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "pool-prepared-statements=true");
//EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "max-open-prepared-statements=5");//Duplicated with following
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "max-pool-prepared-statement-per-connection-size=5");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "validation-query=select 'x'");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "validation-query-timeout=1");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "test-on-borrow=true");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "test-while-idle=true");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "test-on-return=true");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "time-between-eviction-runs-millis=10000");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "min-evictable-idle-time-millis=12345");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "max-evictable-idle-time-millis=123456");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "filters=stat,log4j");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "maxActive=30");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "initialSize=2");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "maxWait=1234");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "minIdle=2");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "timeBetweenEvictionRunsMillis=10000");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "minEvictableIdleTimeMillis=12345");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "testWhileIdle=true");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "testOnBorrow=true");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "testOnReturn=true");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "poolPreparedStatements=true");
EnvironmentTestUtils.addEnvironment(this.context, PREFIX + "maxOpenPreparedStatements=15");
this.context.refresh();
DruidDataSource ds = this.context.getBean(DruidDataSource.class);
assertThat(ds.getUrl()).isEqualTo("jdbc:h2:file:./demo-db");
assertThat(ds.getProxyFilters().size()).isEqualTo(2);
assertThat(ds.getMaxActive()).isEqualTo(30);
assertThat(ds.getInitialSize()).isEqualTo(2);
assertThat(ds.getMaxWait()).isEqualTo(1234);
assertThat(ds.getMaxActive()).isEqualTo(30);
assertThat(ds.getMinIdle()).isEqualTo(2);
assertThat(ds.getTimeBetweenEvictionRunsMillis()).isEqualTo(10000);
assertThat(ds.getMinEvictableIdleTimeMillis()).isEqualTo(12345);
assertThat(ds.getMaxWait()).isEqualTo(1234);
assertThat(ds.isPoolPreparedStatements()).isTrue();
//assertThat(ds.getMaxOpenPreparedStatements()).isEqualTo(5); //Duplicated with following
assertThat(ds.getMaxPoolPreparedStatementPerConnectionSize()).isEqualTo(5);
assertThat(ds.getValidationQuery()).isEqualTo("select 'x'");
assertThat(ds.getValidationQueryTimeout()).isEqualTo(1);
assertThat(ds.isTestWhileIdle()).isTrue();
assertThat(ds.isTestOnBorrow()).isTrue();
assertThat(ds.isTestOnReturn()).isTrue();
assertThat(ds.isPoolPreparedStatements()).isTrue();
assertThat(ds.getMaxOpenPreparedStatements()).isEqualTo(15);
assertThat(ds.getTimeBetweenEvictionRunsMillis()).isEqualTo(10000);
assertThat(ds.getMinEvictableIdleTimeMillis()).isEqualTo(12345);
assertThat(ds.getMaxEvictableIdleTimeMillis()).isEqualTo(123456);
assertThat(ds.getProxyFilters().size()).isEqualTo(2);
}
@Configuration
@EnableConfigurationProperties
@Import(DruidDataSourceAutoConfigure.class)
protected static class DruidDataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource.druid")
public DataSource dataSource() {
return DruidDataSourceBuilder.create().build();
}
}
}