diff --git a/TODO.md b/TODO.md
index 8a0dac6..0ec4c3d 100644
--- a/TODO.md
+++ b/TODO.md
@@ -2,8 +2,7 @@
## 1.0.2
1. ~~增加 `WallConfig` 的提示~~
-2. 增加 `ConfigFilter` 的配置,替换默认的 ConnectProperties 方式
-3. 优化配置项的友好提示
+2. ~~增加多数据源支持~~
## 1.0.3
-1. 增加读写分离
\ No newline at end of file
+1. 增加 `ConfigFilter` 的配置,替换默认的 ConnectProperties 方式
\ No newline at end of file
diff --git a/druid-spring-boot-autoconfigure/pom.xml b/druid-spring-boot-autoconfigure/pom.xml
index 2e7fb55..85624dd 100644
--- a/druid-spring-boot-autoconfigure/pom.xml
+++ b/druid-spring-boot-autoconfigure/pom.xml
@@ -22,6 +22,10 @@
org.springframework.boot
spring-boot-configuration-processor
+
+ org.springframework
+ spring-jdbc
+
javax.servlet
javax.servlet-api
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DataSourceInitializerConfiguration.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DataSourceInitializerConfiguration.java
new file mode 100644
index 0000000..7de6e69
--- /dev/null
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DataSourceInitializerConfiguration.java
@@ -0,0 +1,30 @@
+package com.github.trang.druid;
+
+import com.github.trang.druid.datasource.init.DataSourceInitializer;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * 支持数据源初始化时执行 SQL
+ *
+ * 照搬自 #{@link org.springframework.boot.autoconfigure.jdbc.DataSourceInitializer}
+ *
+ * 在多数据源场景下,#{@link DataSourceAutoConfiguration} 会报 #{@code DataSource} 和
+ * #{@code DataSourceInitializer} 的循环依赖,目前的解决办法是排除 #{@link DataSourceAutoConfiguration},
+ * 但是这样一来,Spring Boot 在数据源初始化时执行 SQL 的特性会被移除,此类是为了保留该特性
+ *
+ * @author trang
+ */
+public class DataSourceInitializerConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean(DataSourceInitializer.class)
+ public com.github.trang.druid.datasource.init.DataSourceInitializer dataSourceInitializer
+ (DataSourceProperties properties, ApplicationContext applicationContext) {
+ return new DataSourceInitializer(properties, applicationContext);
+ }
+
+}
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidAutoConfiguration.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidAutoConfiguration.java
index 7402872..1870b0c 100644
--- a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidAutoConfiguration.java
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidAutoConfiguration.java
@@ -1,6 +1,5 @@
package com.github.trang.druid;
-import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.config.ConfigFilter;
import com.alibaba.druid.filter.logging.CommonsLogFilter;
import com.alibaba.druid.filter.logging.Log4j2Filter;
@@ -10,29 +9,24 @@ import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
+import com.github.trang.druid.datasource.DruidParentDataSource;
+import com.github.trang.druid.properties.DruidProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
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;
import org.springframework.context.annotation.Import;
-import org.springframework.util.StringUtils;
import javax.sql.DataSource;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Stream;
-import static com.github.trang.druid.DruidProperties.*;
-import static java.util.stream.Collectors.toList;
+import static com.github.trang.druid.properties.DruidProperties.*;
/**
* Druid 自动配置
@@ -76,6 +70,7 @@ public class DruidAutoConfiguration {
@ConditionalOnProperty(prefix = DRUID_CONFIG_FILTER_PREFIX, name = "enabled", havingValue = "true")
@Bean
+ @ConfigurationProperties(DRUID_CONFIG_FILTER_PREFIX)
public ConfigFilter configFilter() {
log.debug("druid config-filter init...");
return new ConfigFilter();
@@ -113,42 +108,11 @@ public class DruidAutoConfiguration {
return new CommonsLogFilter();
}
- /*
- * 不使用 @Value 注入,避免因为找不到值抛出 NPE
- */
- @Autowired
- private DataSourceProperties dataSourceProperties;
-
@ConditionalOnMissingBean(DataSource.class)
@Bean(initMethod = "init", destroyMethod = "close")
- @ConfigurationProperties(DRUID_DATA_SOURCE_PREFIX)
- public DruidDataSource dataSource(@Autowired(required = false) StatFilter statFilter,
- @Autowired(required = false) WallFilter wallFilter,
- @Autowired(required = false) ConfigFilter configFilter,
- @Autowired(required = false) Slf4jLogFilter slf4jLogFilter,
- @Autowired(required = false) Log4jFilter log4jFilter,
- @Autowired(required = false) Log4j2Filter log4j2Filter,
- @Autowired(required = false) CommonsLogFilter commonsLogFilter) {
+ public DruidDataSource dataSource() {
log.debug("druid data-source init...");
- DruidDataSource dataSource = new DruidDataSource();
- if (!StringUtils.isEmpty(dataSourceProperties.getDriverClassName())) {
- dataSource.setDriverClassName(dataSourceProperties.getDriverClassName());
- }
- if (!StringUtils.isEmpty(dataSourceProperties.getUrl())) {
- dataSource.setUrl(dataSourceProperties.getUrl());
- }
- if (!StringUtils.isEmpty(dataSourceProperties.getUsername())) {
- dataSource.setUsername(dataSourceProperties.getUsername());
- }
- if (!StringUtils.isEmpty(dataSourceProperties.getPassword())) {
- dataSource.setPassword(dataSourceProperties.getPassword());
- }
- List filters = Stream.of(statFilter, wallFilter, configFilter, slf4jLogFilter, log4jFilter,
- log4j2Filter, commonsLogFilter)
- .filter(Objects::nonNull)
- .collect(toList());
- dataSource.setProxyFilters(filters);
- return dataSource;
+ return new DruidParentDataSource() {};
}
}
\ No newline at end of file
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidProperties.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidProperties.java
deleted file mode 100644
index eda02f6..0000000
--- a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidProperties.java
+++ /dev/null
@@ -1,255 +0,0 @@
-package com.github.trang.druid;
-
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.context.properties.NestedConfigurationProperty;
-
-import static com.github.trang.druid.DruidProperties.DRUID_DATA_SOURCE_PREFIX;
-
-/**
- * Druid 自定义配置
- *
- * @author trang
- */
-@ConfigurationProperties(DRUID_DATA_SOURCE_PREFIX)
-public class DruidProperties {
-
- public static final String DRUID_DATA_SOURCE_PREFIX = "spring.datasource.druid";
- public static final String DRUID_STAT_FILTER_PREFIX = "spring.datasource.druid.stat";
- public static final String DRUID_WALL_FILTER_PREFIX = "spring.datasource.druid.wall";
- public static final String DRUID_WALL_CONFIG_PREFIX = "spring.datasource.druid.wall.config";
- public static final String DRUID_CONFIG_FILTER_PREFIX = "spring.datasource.druid.config";
- public static final String DRUID_SLF4J_FILTER_PREFIX = "spring.datasource.druid.slf4j";
- public static final String DRUID_LOG4J_FILTER_PREFIX = "spring.datasource.druid.log4j";
- public static final String DRUID_LOG4J2_FILTER_PREFIX = "spring.datasource.druid.log4j2";
- public static final String DRUID_COMMONS_LOG_FILTER_PREFIX = "spring.datasource.druid.commons-log";
- public static final String DRUID_WEB_STATE_PREFIX = "spring.datasource.druid.web-stat";
- public static final String DRUID_AOP_STAT_PREFIX = "spring.datasource.druid.aop-stat";
- public static final String DRUID_STAT_VIEW_SERVLET_PREFIX = "spring.datasource.druid.stat-view-servlet";
-
- @NestedConfigurationProperty
- private WebStat webStat = new WebStat();
- @NestedConfigurationProperty
- private AopStat aopStat = new AopStat();
- @NestedConfigurationProperty
- private StatViewServlet statViewServlet = new StatViewServlet();
-
- public WebStat getWebStat() {
- return webStat;
- }
-
- public void setWebStat(WebStat webStat) {
- this.webStat = webStat;
- }
-
- public AopStat getAopStat() {
- return aopStat;
- }
-
- public void setAopStat(AopStat aopStat) {
- this.aopStat = aopStat;
- }
-
- public StatViewServlet getStatViewServlet() {
- return statViewServlet;
- }
-
- public void setStatViewServlet(StatViewServlet statViewServlet) {
- this.statViewServlet = statViewServlet;
- }
-
- /**
- * WebStat 自定义配置
- *
- * @author trang
- */
- public static class WebStat {
- // 是否开启 web-jdbc 监控,默认否
- private boolean enabled;
- // 过滤器 url 的映射规则
- private String urlPatterns = "/*";
- // 过滤器 url 的排除规则
- private String exclusions = "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*";
- // 是否开启 session 统计,默认否
- private boolean sessionStatEnable;
- // session 统计的最大值,默认值 1000
- private Integer sessionStatMaxCount = 1000;
- // 配置当前 session 的用户
- private String principalSessionName;
- // 配置当前 cookie 的用户
- private String principalCookieName;
- // 是否开启监控单个 url 调用的 sql 列表,默认是
- private boolean profileEnable = true;
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- public String getUrlPatterns() {
- return urlPatterns;
- }
-
- public void setUrlPatterns(String urlPatterns) {
- this.urlPatterns = urlPatterns;
- }
-
- public String getExclusions() {
- return exclusions;
- }
-
- public void setExclusions(String exclusions) {
- this.exclusions = exclusions;
- }
-
- public boolean isSessionStatEnable() {
- return sessionStatEnable;
- }
-
- public void setSessionStatEnable(boolean sessionStatEnable) {
- this.sessionStatEnable = sessionStatEnable;
- }
-
- public Integer getSessionStatMaxCount() {
- return sessionStatMaxCount;
- }
-
- public void setSessionStatMaxCount(Integer sessionStatMaxCount) {
- this.sessionStatMaxCount = sessionStatMaxCount;
- }
-
- public String getPrincipalSessionName() {
- return principalSessionName;
- }
-
- public void setPrincipalSessionName(String principalSessionName) {
- this.principalSessionName = principalSessionName;
- }
-
- public String getPrincipalCookieName() {
- return principalCookieName;
- }
-
- public void setPrincipalCookieName(String principalCookieName) {
- this.principalCookieName = principalCookieName;
- }
-
- public boolean isProfileEnable() {
- return profileEnable;
- }
-
- public void setProfileEnable(boolean profileEnable) {
- this.profileEnable = profileEnable;
- }
-
- }
-
- /**
- * Aop 监控自定义配置
- */
- public static class AopStat {
- // 是否开启基于 aop 的监控,默认否
- private boolean enabled;
- // aop 拦截规则
- private String[] patterns;
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- public String[] getPatterns() {
- return patterns;
- }
-
- public void setPatterns(String[] patterns) {
- this.patterns = patterns;
- }
-
- }
-
- /**
- * StatViewServlet 自定义配置
- *
- * @author trang
- */
- public static class StatViewServlet {
- // 是否开启 Druid 的数据统计页面,默认否
- private boolean enabled= false;
- // Servlet 的映射规则,默认访问 "http://xxx/druid/"
- private String urlMappings = "/druid/*";
- // Druid 统计页面的登陆用户名
- private String loginUsername;
- // Druid 统计页面的登陆密码
- private String loginPassword;
- // Druid 统计页面的访问白名单,默认允许所有人访问
- private String allow;
- // Druid 统计页面的访问黑名单,优先于白名单
- private String deny;
- // 是否允许清空统计数据,默认否
- private boolean resetEnable;
-
- public boolean isEnabled() {
- return enabled;
- }
-
- public void setEnabled(boolean enabled) {
- this.enabled = enabled;
- }
-
- public String getUrlMappings() {
- return urlMappings;
- }
-
- public void setUrlMappings(String urlMappings) {
- this.urlMappings = urlMappings;
- }
-
- public String getLoginUsername() {
- return loginUsername;
- }
-
- public void setLoginUsername(String loginUsername) {
- this.loginUsername = loginUsername;
- }
-
- public String getLoginPassword() {
- return loginPassword;
- }
-
- public void setLoginPassword(String loginPassword) {
- this.loginPassword = loginPassword;
- }
-
- public String getAllow() {
- return allow;
- }
-
- public void setAllow(String allow) {
- this.allow = allow;
- }
-
- public String getDeny() {
- return deny;
- }
-
- public void setDeny(String deny) {
- this.deny = deny;
- }
-
- public boolean isResetEnable() {
- return resetEnable;
- }
-
- public void setResetEnable(boolean resetEnable) {
- this.resetEnable = resetEnable;
- }
-
- }
-
-}
\ No newline at end of file
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidServletConfiguration.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidServletConfiguration.java
index cbecad0..8d64673 100644
--- a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidServletConfiguration.java
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidServletConfiguration.java
@@ -1,15 +1,17 @@
package com.github.trang.druid;
import com.alibaba.druid.support.http.StatViewServlet;
+import com.github.trang.druid.properties.DruidServletProperties.DruidStatViewServletProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.util.StringUtils;
-import static com.github.trang.druid.DruidProperties.DRUID_STAT_VIEW_SERVLET_PREFIX;
+import static com.github.trang.druid.properties.DruidServletProperties.DRUID_STAT_VIEW_SERVLET_PREFIX;
/**
* Druid Servlet 配置
@@ -17,6 +19,7 @@ import static com.github.trang.druid.DruidProperties.DRUID_STAT_VIEW_SERVLET_PRE
* @author trang
*/
@ConditionalOnWebApplication
+@EnableConfigurationProperties(DruidStatViewServletProperties.class)
public class DruidServletConfiguration {
private static final Logger log = LoggerFactory.getLogger(DruidServletConfiguration.class);
@@ -24,31 +27,30 @@ public class DruidServletConfiguration {
/**
* Druid 提供了一个 StatViewServlet 用于展示 Druid 的统计信息
* 这个 StatViewServlet 的用途包括:
- * 1. 提供监控信息展示的 HTML 页面
- * 2. 提供监控信息的 JSON API
+ * 1. 提供监控信息展示的 HTML 页面
+ * 2. 提供监控信息的 JSON API
*/
@ConditionalOnProperty(prefix = DRUID_STAT_VIEW_SERVLET_PREFIX, name = "enabled", havingValue = "true")
@Bean
- public ServletRegistrationBean servletRegistrationBean(DruidProperties properties) {
+ public ServletRegistrationBean servletRegistrationBean(DruidStatViewServletProperties properties) {
log.debug("druid stat-view-servlet init...");
ServletRegistrationBean registration = new ServletRegistrationBean();
- DruidProperties.StatViewServlet config = properties.getStatViewServlet();
StatViewServlet statViewServlet = new StatViewServlet();
registration.setServlet(statViewServlet);
- registration.addUrlMappings(config.getUrlMappings());
- if (!StringUtils.isEmpty(config.getLoginUsername())) {
- registration.addInitParameter("loginUsername", config.getLoginUsername());
+ registration.addUrlMappings(properties.getUrlMappings());
+ if (!StringUtils.isEmpty(properties.getLoginUsername())) {
+ registration.addInitParameter("loginUsername", properties.getLoginUsername());
}
- if (!StringUtils.isEmpty(config.getLoginPassword())) {
- registration.addInitParameter("loginPassword", config.getLoginPassword());
+ if (!StringUtils.isEmpty(properties.getLoginPassword())) {
+ registration.addInitParameter("loginPassword", properties.getLoginPassword());
}
- if (!StringUtils.isEmpty(config.getAllow())) {
- registration.addInitParameter("allow", config.getAllow());
+ if (!StringUtils.isEmpty(properties.getAllow())) {
+ registration.addInitParameter("allow", properties.getAllow());
}
- if (!StringUtils.isEmpty(config.getDeny())) {
- registration.addInitParameter("deny", config.getDeny());
+ if (!StringUtils.isEmpty(properties.getDeny())) {
+ registration.addInitParameter("deny", properties.getDeny());
}
- registration.addInitParameter("resetEnable", Boolean.toString(config.isResetEnable()));
+ registration.addInitParameter("resetEnable", Boolean.toString(properties.isResetEnable()));
return registration;
}
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidStatConfiguration.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidStatConfiguration.java
index 97e5213..785362b 100644
--- a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidStatConfiguration.java
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/DruidStatConfiguration.java
@@ -2,7 +2,8 @@ package com.github.trang.druid;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.support.spring.stat.DruidStatInterceptor;
-import com.github.trang.druid.DruidProperties.WebStat;
+import com.github.trang.druid.properties.DruidStatProperties.DruidAopStatProperties;
+import com.github.trang.druid.properties.DruidStatProperties.DruidWebStatProperties;
import org.aopalliance.aop.Advice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -12,18 +13,20 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.util.StringUtils;
-import static com.github.trang.druid.DruidProperties.DRUID_AOP_STAT_PREFIX;
-import static com.github.trang.druid.DruidProperties.DRUID_WEB_STATE_PREFIX;
+import static com.github.trang.druid.properties.DruidStatProperties.DRUID_AOP_STAT_PREFIX;
+import static com.github.trang.druid.properties.DruidStatProperties.DRUID_WEB_STAT_PREFIX;
/**
* Druid 监控配置
*
* @author trang
*/
+@EnableConfigurationProperties({DruidWebStatProperties.class, DruidAopStatProperties.class})
public class DruidStatConfiguration {
/**
@@ -44,9 +47,9 @@ public class DruidStatConfiguration {
}
@Bean
- public RegexpMethodPointcutAdvisor druidStatAdvisor(DruidProperties druidProperties,
+ public RegexpMethodPointcutAdvisor druidStatAdvisor(DruidAopStatProperties properties,
DruidStatInterceptor druidStatInterceptor) {
- return new RegexpMethodPointcutAdvisor(druidProperties.getAopStat().getPatterns(), druidStatInterceptor);
+ return new RegexpMethodPointcutAdvisor(properties.getPatterns(), druidStatInterceptor);
}
@Bean
@@ -67,27 +70,26 @@ public class DruidStatConfiguration {
private static final Logger log = LoggerFactory.getLogger(DruidStatConfiguration.class);
- @ConditionalOnProperty(prefix = DRUID_WEB_STATE_PREFIX, name = "enabled", havingValue = "true")
+ @ConditionalOnProperty(prefix = DRUID_WEB_STAT_PREFIX, name = "enabled", havingValue = "true")
@Bean
- public FilterRegistrationBean filterRegistrationBean(DruidProperties properties) {
+ public FilterRegistrationBean filterRegistrationBean(DruidWebStatProperties properties) {
log.debug("druid web-stat-filter init...");
FilterRegistrationBean registration = new FilterRegistrationBean();
- WebStat config = properties.getWebStat();
WebStatFilter filter = new WebStatFilter();
registration.setFilter(filter);
- registration.addUrlPatterns(config.getUrlPatterns());
- registration.addInitParameter("exclusions", config.getExclusions());
- registration.addInitParameter("sessionStatEnable", Boolean.toString(config.isSessionStatEnable()));
- if (!StringUtils.isEmpty(config.getSessionStatMaxCount())) {
- registration.addInitParameter("sessionStatMaxCount",Integer.toString(config.getSessionStatMaxCount()));
+ registration.addUrlPatterns(properties.getUrlPatterns());
+ registration.addInitParameter("exclusions", properties.getExclusions());
+ registration.addInitParameter("sessionStatEnable", Boolean.toString(properties.isSessionStatEnable()));
+ if (!StringUtils.isEmpty(properties.getSessionStatMaxCount())) {
+ registration.addInitParameter("sessionStatMaxCount",Integer.toString(properties.getSessionStatMaxCount()));
}
- if (!StringUtils.isEmpty(config.getPrincipalSessionName())) {
- registration.addInitParameter("principalSessionName", config.getPrincipalSessionName());
+ if (!StringUtils.isEmpty(properties.getPrincipalSessionName())) {
+ registration.addInitParameter("principalSessionName", properties.getPrincipalSessionName());
}
- if (!StringUtils.isEmpty(config.getPrincipalCookieName())) {
- registration.addInitParameter("principalCookieName", config.getPrincipalCookieName());
+ if (!StringUtils.isEmpty(properties.getPrincipalCookieName())) {
+ registration.addInitParameter("principalCookieName", properties.getPrincipalCookieName());
}
- registration.addInitParameter("profileEnable", Boolean.toString(config.isProfileEnable()));
+ registration.addInitParameter("profileEnable", Boolean.toString(properties.isProfileEnable()));
return registration;
}
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/datasource/DruidMultiDataSource.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/datasource/DruidMultiDataSource.java
new file mode 100644
index 0000000..dc98d74
--- /dev/null
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/datasource/DruidMultiDataSource.java
@@ -0,0 +1,10 @@
+package com.github.trang.druid.datasource;
+
+/**
+ * Druid 多数据源支持,支持共用公共参数
+ *
+ * @author trang
+ */
+public class DruidMultiDataSource extends DruidParentDataSource {
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/datasource/DruidParentDataSource.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/datasource/DruidParentDataSource.java
new file mode 100644
index 0000000..fca3b00
--- /dev/null
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/datasource/DruidParentDataSource.java
@@ -0,0 +1,72 @@
+package com.github.trang.druid.datasource;
+
+import com.alibaba.druid.filter.Filter;
+import com.alibaba.druid.filter.config.ConfigFilter;
+import com.alibaba.druid.filter.logging.CommonsLogFilter;
+import com.alibaba.druid.filter.logging.Log4j2Filter;
+import com.alibaba.druid.filter.logging.Log4jFilter;
+import com.alibaba.druid.filter.logging.Slf4jLogFilter;
+import com.alibaba.druid.filter.stat.StatFilter;
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.wall.WallFilter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PostConstruct;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import static com.github.trang.druid.properties.DruidProperties.DRUID_DATA_SOURCE_PREFIX;
+
+/**
+ * Druid 多数据源支持,支持共用公共参数
+ *
+ * @author trang
+ */
+@ConfigurationProperties(DRUID_DATA_SOURCE_PREFIX)
+public abstract class DruidParentDataSource extends DruidDataSource {
+
+ @Autowired(required = false)
+ private StatFilter statFilter;
+ @Autowired(required = false)
+ private WallFilter wallFilter;
+ @Autowired(required = false)
+ private ConfigFilter configFilter;
+ @Autowired(required = false)
+ private Slf4jLogFilter slf4jLogFilter;
+ @Autowired(required = false)
+ private Log4jFilter log4jFilter;
+ @Autowired(required = false)
+ private Log4j2Filter log4j2Filter;
+ @Autowired(required = false)
+ private CommonsLogFilter commonsLogFilter;
+ // 不使用 @Value 注入,避免因为找不到值抛出 NPE
+ @Autowired
+ private DataSourceProperties dataSourceProperties;
+
+ @PostConstruct
+ public void initCommonParams() {
+ if (!StringUtils.isEmpty(dataSourceProperties.getDriverClassName())) {
+ super.setDriverClassName(dataSourceProperties.getDriverClassName());
+ }
+ if (!StringUtils.isEmpty(dataSourceProperties.getUrl())) {
+ super.setUrl(dataSourceProperties.getUrl());
+ }
+ if (!StringUtils.isEmpty(dataSourceProperties.getUsername())) {
+ super.setUsername(dataSourceProperties.getUsername());
+ }
+ if (!StringUtils.isEmpty(dataSourceProperties.getPassword())) {
+ super.setPassword(dataSourceProperties.getPassword());
+ }
+ List filters = super.getProxyFilters();
+ Stream.of(statFilter, wallFilter, configFilter, slf4jLogFilter, log4jFilter, log4j2Filter,
+ commonsLogFilter)
+ .filter(Objects::nonNull)
+ .filter(filter -> !filters.contains(filter))
+ .forEach(filters::add);
+ }
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/datasource/init/DataSourceInitializer.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/datasource/init/DataSourceInitializer.java
new file mode 100644
index 0000000..9e35c79
--- /dev/null
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/datasource/init/DataSourceInitializer.java
@@ -0,0 +1,177 @@
+package com.github.trang.druid.datasource.init;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceInitializedEvent;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
+import org.springframework.boot.context.config.ResourceNotFoundException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationListener;
+import org.springframework.core.io.Resource;
+import org.springframework.jdbc.config.SortedResourcesFactoryBean;
+import org.springframework.jdbc.datasource.init.DatabasePopulatorUtils;
+import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.PostConstruct;
+import javax.sql.DataSource;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Bean to handle {@link DataSource} initialization by running {@literal schema-*.sql} on
+ * {@link PostConstruct} and {@literal data-*.sql} SQL scripts on a
+ * {@link DataSourceInitializedEvent}.
+ *
+ * @author Dave Syer
+ * @author Phillip Webb
+ * @author Eddú Meléndez
+ * @author Stephane Nicoll
+ * @author Kazuki Shimizu
+ * @since 1.1.0
+ * @see com.github.trang.druid.DataSourceInitializerConfiguration
+ */
+public class DataSourceInitializer implements ApplicationListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(DataSourceInitializer.class);
+
+ private final DataSourceProperties properties;
+
+ private final ApplicationContext applicationContext;
+
+ private DataSource dataSource;
+
+ private boolean initialized = false;
+
+ public DataSourceInitializer(DataSourceProperties properties,
+ ApplicationContext applicationContext) {
+ this.properties = properties;
+ this.applicationContext = applicationContext;
+ }
+
+ @PostConstruct
+ public void init() {
+ if (!this.properties.isInitialize()) {
+ logger.debug("Initialization disabled (not running DDL scripts)");
+ return;
+ }
+ if (this.applicationContext.getBeanNamesForType(DataSource.class, false,
+ false).length > 0) {
+ this.dataSource = this.applicationContext.getBean(DataSource.class);
+ }
+ if (this.dataSource == null) {
+ logger.debug("No DataSource found so not initializing");
+ return;
+ }
+ runSchemaScripts();
+ }
+
+ private void runSchemaScripts() {
+ List scripts = getScripts("spring.datasource.schema",
+ this.properties.getSchema(), "schema");
+ if (!scripts.isEmpty()) {
+ String username = this.properties.getSchemaUsername();
+ String password = this.properties.getSchemaPassword();
+ runScripts(scripts, username, password);
+ try {
+ this.applicationContext
+ .publishEvent(new DataSourceInitializedEvent(this.dataSource));
+ // The listener might not be registered yet, so don't rely on it.
+ if (!this.initialized) {
+ runDataScripts();
+ this.initialized = true;
+ }
+ } catch (IllegalStateException ex) {
+ logger.warn("Could not send event to complete DataSource initialization ("
+ + ex.getMessage() + ")");
+ }
+ }
+ }
+
+ @Override
+ public void onApplicationEvent(DataSourceInitializedEvent event) {
+ if (!this.properties.isInitialize()) {
+ logger.debug("Initialization disabled (not running data scripts)");
+ return;
+ }
+ // NOTE the event can happen more than once and
+ // the event datasource is not used here
+ if (!this.initialized) {
+ runDataScripts();
+ this.initialized = true;
+ }
+ }
+
+ private void runDataScripts() {
+ List scripts = getScripts("spring.datasource.data",
+ this.properties.getData(), "data");
+ String username = this.properties.getDataUsername();
+ String password = this.properties.getDataPassword();
+ runScripts(scripts, username, password);
+ }
+
+ private List getScripts(String propertyName, List resources,
+ String fallback) {
+ if (resources != null) {
+ return getResources(propertyName, resources, true);
+ }
+ String platform = this.properties.getPlatform();
+ List fallbackResources = new ArrayList();
+ fallbackResources.add("classpath*:" + fallback + "-" + platform + ".sql");
+ fallbackResources.add("classpath*:" + fallback + ".sql");
+ return getResources(propertyName, fallbackResources, false);
+ }
+
+ private List getResources(String propertyName, List locations,
+ boolean validate) {
+ List resources = new ArrayList();
+ for (String location : locations) {
+ for (Resource resource : doGetResources(location)) {
+ if (resource.exists()) {
+ resources.add(resource);
+ } else if (validate) {
+ throw new ResourceNotFoundException(propertyName, resource);
+ }
+ }
+ }
+ return resources;
+ }
+
+ private Resource[] doGetResources(String location) {
+ try {
+ SortedResourcesFactoryBean factory = new SortedResourcesFactoryBean(
+ this.applicationContext, Collections.singletonList(location));
+ factory.afterPropertiesSet();
+ return factory.getObject();
+ } catch (Exception ex) {
+ throw new IllegalStateException("Unable to load resources from " + location,
+ ex);
+ }
+ }
+
+ private void runScripts(List resources, String username, String password) {
+ if (resources.isEmpty()) {
+ return;
+ }
+ ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
+ populator.setContinueOnError(this.properties.isContinueOnError());
+ populator.setSeparator(this.properties.getSeparator());
+ if (this.properties.getSqlScriptEncoding() != null) {
+ populator.setSqlScriptEncoding(this.properties.getSqlScriptEncoding().name());
+ }
+ for (Resource resource : resources) {
+ populator.addScript(resource);
+ }
+ DataSource dataSource = this.dataSource;
+ if (StringUtils.hasText(username) && StringUtils.hasText(password)) {
+ dataSource = DataSourceBuilder.create(this.properties.getClassLoader())
+ .driverClassName(this.properties.determineDriverClassName())
+ .url(this.properties.determineUrl()).username(username)
+ .password(password).build();
+ }
+ DatabasePopulatorUtils.execute(populator, dataSource);
+ }
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/properties/DruidProperties.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/properties/DruidProperties.java
new file mode 100644
index 0000000..11f8443
--- /dev/null
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/properties/DruidProperties.java
@@ -0,0 +1,20 @@
+package com.github.trang.druid.properties;
+
+/**
+ * Druid 自定义配置
+ *
+ * @author trang
+ */
+public class DruidProperties {
+
+ public static final String DRUID_DATA_SOURCE_PREFIX = "spring.datasource.druid";
+ public static final String DRUID_STAT_FILTER_PREFIX = "spring.datasource.druid.stat";
+ public static final String DRUID_WALL_FILTER_PREFIX = "spring.datasource.druid.wall";
+ public static final String DRUID_WALL_CONFIG_PREFIX = "spring.datasource.druid.wall.config";
+ public static final String DRUID_CONFIG_FILTER_PREFIX = "spring.datasource.druid.config";
+ public static final String DRUID_SLF4J_FILTER_PREFIX = "spring.datasource.druid.slf4j";
+ public static final String DRUID_LOG4J_FILTER_PREFIX = "spring.datasource.druid.log4j";
+ public static final String DRUID_LOG4J2_FILTER_PREFIX = "spring.datasource.druid.log4j2";
+ public static final String DRUID_COMMONS_LOG_FILTER_PREFIX = "spring.datasource.druid.commons-log";
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/properties/DruidServletProperties.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/properties/DruidServletProperties.java
new file mode 100644
index 0000000..858bc7d
--- /dev/null
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/properties/DruidServletProperties.java
@@ -0,0 +1,95 @@
+package com.github.trang.druid.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Druid 数据展示配置
+ *
+ * @author trang
+ */
+public class DruidServletProperties {
+
+ public static final String DRUID_STAT_VIEW_SERVLET_PREFIX = "spring.datasource.druid.stat-view-servlet";
+
+ /**
+ * StatViewServlet 自定义配置
+ *
+ * @author trang
+ */
+ @ConfigurationProperties(DRUID_STAT_VIEW_SERVLET_PREFIX)
+ public static class DruidStatViewServletProperties {
+
+ // 是否开启 Druid 的数据统计页面,默认否
+ private boolean enabled;
+ // Servlet 的映射规则,默认访问 "http://xxx/druid/"
+ private String urlMappings = "/druid/*";
+ // Druid 统计页面的登陆用户名
+ private String loginUsername;
+ // Druid 统计页面的登陆密码
+ private String loginPassword;
+ // Druid 统计页面的访问白名单,默认允许所有人访问
+ private String allow;
+ // Druid 统计页面的访问黑名单,优先于白名单
+ private String deny;
+ // 是否允许清空统计数据,默认否
+ private boolean resetEnable;
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getUrlMappings() {
+ return urlMappings;
+ }
+
+ public void setUrlMappings(String urlMappings) {
+ this.urlMappings = urlMappings;
+ }
+
+ public String getLoginUsername() {
+ return loginUsername;
+ }
+
+ public void setLoginUsername(String loginUsername) {
+ this.loginUsername = loginUsername;
+ }
+
+ public String getLoginPassword() {
+ return loginPassword;
+ }
+
+ public void setLoginPassword(String loginPassword) {
+ this.loginPassword = loginPassword;
+ }
+
+ public String getAllow() {
+ return allow;
+ }
+
+ public void setAllow(String allow) {
+ this.allow = allow;
+ }
+
+ public String getDeny() {
+ return deny;
+ }
+
+ public void setDeny(String deny) {
+ this.deny = deny;
+ }
+
+ public boolean isResetEnable() {
+ return resetEnable;
+ }
+
+ public void setResetEnable(boolean resetEnable) {
+ this.resetEnable = resetEnable;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/properties/DruidStatProperties.java b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/properties/DruidStatProperties.java
new file mode 100644
index 0000000..78ff872
--- /dev/null
+++ b/druid-spring-boot-autoconfigure/src/main/java/com/github/trang/druid/properties/DruidStatProperties.java
@@ -0,0 +1,135 @@
+package com.github.trang.druid.properties;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * Druid 监控配置
+ *
+ * @author trang
+ */
+public class DruidStatProperties {
+
+ public static final String DRUID_WEB_STAT_PREFIX = "spring.datasource.druid.web-stat";
+ public static final String DRUID_AOP_STAT_PREFIX = "spring.datasource.druid.aop-stat";
+
+ /**
+ * WebStat 自定义配置
+ *
+ * @author trang
+ */
+ @ConfigurationProperties(DRUID_WEB_STAT_PREFIX)
+ public static class DruidWebStatProperties {
+
+ // 是否开启 web-jdbc 监控,默认否
+ private boolean enabled;
+ // 过滤器 url 的映射规则
+ private String urlPatterns = "/*";
+ // 过滤器 url 的排除规则
+ private String exclusions = "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*";
+ // 是否开启 session 统计,默认否
+ private boolean sessionStatEnable;
+ // session 统计的最大值,默认值 1000
+ private Integer sessionStatMaxCount = 1000;
+ // 配置当前 session 的用户
+ private String principalSessionName;
+ // 配置当前 cookie 的用户
+ private String principalCookieName;
+ // 是否开启监控单个 url 调用的 sql 列表,默认是
+ private boolean profileEnable = true;
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getUrlPatterns() {
+ return urlPatterns;
+ }
+
+ public void setUrlPatterns(String urlPatterns) {
+ this.urlPatterns = urlPatterns;
+ }
+
+ public String getExclusions() {
+ return exclusions;
+ }
+
+ public void setExclusions(String exclusions) {
+ this.exclusions = exclusions;
+ }
+
+ public boolean isSessionStatEnable() {
+ return sessionStatEnable;
+ }
+
+ public void setSessionStatEnable(boolean sessionStatEnable) {
+ this.sessionStatEnable = sessionStatEnable;
+ }
+
+ public Integer getSessionStatMaxCount() {
+ return sessionStatMaxCount;
+ }
+
+ public void setSessionStatMaxCount(Integer sessionStatMaxCount) {
+ this.sessionStatMaxCount = sessionStatMaxCount;
+ }
+
+ public String getPrincipalSessionName() {
+ return principalSessionName;
+ }
+
+ public void setPrincipalSessionName(String principalSessionName) {
+ this.principalSessionName = principalSessionName;
+ }
+
+ public String getPrincipalCookieName() {
+ return principalCookieName;
+ }
+
+ public void setPrincipalCookieName(String principalCookieName) {
+ this.principalCookieName = principalCookieName;
+ }
+
+ public boolean isProfileEnable() {
+ return profileEnable;
+ }
+
+ public void setProfileEnable(boolean profileEnable) {
+ this.profileEnable = profileEnable;
+ }
+
+ }
+
+ /**
+ * Aop 监控自定义配置
+ */
+ @ConfigurationProperties(DRUID_AOP_STAT_PREFIX)
+ public static class DruidAopStatProperties {
+
+ // 是否开启基于 aop 的监控,默认否
+ private boolean enabled;
+ // aop 拦截规则
+ private String[] patterns;
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String[] getPatterns() {
+ return patterns;
+ }
+
+ public void setPatterns(String[] patterns) {
+ this.patterns = patterns;
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/druid-spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
index f2b1b95..9a585b9 100644
--- a/druid-spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
+++ b/druid-spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json
@@ -3,64 +3,64 @@
{
"name": "spring.datasource.druid.stat.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid stat filter are enabled.",
+ "description": "Whether or not druid stat-filter are enabled.",
"defaultValue": true
},
{
"name": "spring.datasource.druid.wall.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid wall filter are enabled.",
+ "description": "Whether or not druid wall-filter are enabled.",
"defaultValue": false
},
{
"name": "spring.datasource.druid.config.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid config filter are enabled.",
+ "description": "Whether or not druid config-filter are enabled.",
"defaultValue": false
},
{
"name": "spring.datasource.druid.slf4j.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid slf4j filter are enabled.",
+ "description": "Whether or not druid slf4j-filter are enabled.",
"defaultValue": false
},
{
"name": "spring.datasource.druid.log4j.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid log4j filter are enabled.",
+ "description": "Whether or not druid log4j-filter are enabled.",
"defaultValue": false
},
{
"name": "spring.datasource.druid.log4j2.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid log4j2 filter are enabled.",
+ "description": "Whether or not druid log4j2-filter are enabled.",
"defaultValue": false
},
{
"name": "spring.datasource.druid.commons-log.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid commons logging filter are enabled.",
+ "description": "Whether or not druid commons-log-filter are enabled.",
"defaultValue": false
},
{
"name": "spring.datasource.druid.aop-stat.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid aop stat are enabled.",
- "sourceType": "com.github.trang.druid.DruidProperties$AopStat",
+ "description": "Whether or not druid aop-stat are enabled.",
+ "sourceType": "com.github.trang.druid.properties.DruidStatProperties$DruidAopStatProperties",
"defaultValue": false
},
{
"name": "spring.datasource.druid.web-stat.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid web stat are enabled.",
- "sourceType": "com.github.trang.druid.DruidProperties$WebStat",
+ "description": "Whether or not druid web-stat are enabled.",
+ "sourceType": "com.github.trang.druid.properties.DruidStatProperties$DruidWebStatProperties",
"defaultValue": false
},
{
"name": "spring.datasource.druid.stat-view-servlet.enabled",
"type": "java.lang.Boolean",
- "description": "Whether or not druid stat view servlet are enabled.",
- "sourceType": "com.github.trang.druid.DruidProperties$StatViewServlet",
+ "description": "Whether or not druid stat-view-servlet are enabled.",
+ "sourceType": "com.github.trang.druid.properties.DruidServletProperties$DruidStatViewServletProperties",
"defaultValue": false
}
],
diff --git a/druid-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/druid-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
index d308da2..d3f9714 100644
--- a/druid-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
+++ b/druid-spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories
@@ -1 +1,2 @@
-org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.github.trang.druid.DruidAutoConfiguration
\ No newline at end of file
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+com.github.trang.druid.DruidAutoConfiguration
\ No newline at end of file
diff --git a/druid-spring-boot-samples/pom.xml b/druid-spring-boot-samples/pom.xml
index d8e17d1..cf851a3 100644
--- a/druid-spring-boot-samples/pom.xml
+++ b/druid-spring-boot-samples/pom.xml
@@ -39,6 +39,16 @@
org.springframework.boot
spring-boot-starter-web
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ org.hibernate
+ hibernate-validator
+
+
org.springframework.boot
@@ -47,6 +57,12 @@
org.mybatis.spring.boot
mybatis-spring-boot-starter
+
+
+ org.apache.tomcat
+ tomcat-jdbc
+
+
com.github.drtrang
diff --git a/druid-spring-boot-samples/src/main/java/com/github/trang/druid/DruidSpringBootStarterApplication.java b/druid-spring-boot-samples/src/main/java/com/github/trang/druid/DruidSpringBootStarterApplication.java
index dbec32c..646c90b 100644
--- a/druid-spring-boot-samples/src/main/java/com/github/trang/druid/DruidSpringBootStarterApplication.java
+++ b/druid-spring-boot-samples/src/main/java/com/github/trang/druid/DruidSpringBootStarterApplication.java
@@ -1,6 +1,7 @@
package com.github.trang.druid;
import com.github.trang.druid.mapper.CityMapper;
+import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
@@ -12,6 +13,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
* @author trang
*/
@SpringBootApplication
+@MapperScan("com.github.trang.druid.mapper")
public class DruidSpringBootStarterApplication implements CommandLineRunner {
public static void main(String[] args) {
@@ -24,7 +26,7 @@ public class DruidSpringBootStarterApplication implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
- System.out.println(cityMapper.findByState("CA"));
+ System.out.println(cityMapper.findAll());
}
}
\ No newline at end of file
diff --git a/druid-spring-boot-samples/src/main/java/com/github/trang/druid/config/DynamicDataSource.java b/druid-spring-boot-samples/src/main/java/com/github/trang/druid/config/DynamicDataSource.java
new file mode 100644
index 0000000..5e51775
--- /dev/null
+++ b/druid-spring-boot-samples/src/main/java/com/github/trang/druid/config/DynamicDataSource.java
@@ -0,0 +1,42 @@
+package com.github.trang.druid.config;
+
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+import javax.sql.DataSource;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * 动态数据源,基于简单的轮询算法
+ *
+ * @author trang
+ */
+public class DynamicDataSource extends AbstractRoutingDataSource {
+
+ private AtomicInteger count = new AtomicInteger();
+ private DataSource defaultTargetDataSource;
+ private Map targetDataSources;
+
+ public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) {
+ this.defaultTargetDataSource = defaultTargetDataSource;
+ this.targetDataSources = targetDataSources;
+ }
+
+ @Override
+ protected Object determineCurrentLookupKey() {
+ int i = count.incrementAndGet();
+ List list = new ArrayList<>(targetDataSources.keySet());
+ return list.get(i % list.size());
+ }
+
+ @Override
+ public void afterPropertiesSet() {
+ super.setDefaultTargetDataSource(defaultTargetDataSource);
+ super.setTargetDataSources(new HashMap<>(targetDataSources));
+ super.afterPropertiesSet();
+ }
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-samples/src/main/java/com/github/trang/druid/config/SpringDataSourceConfig.java b/druid-spring-boot-samples/src/main/java/com/github/trang/druid/config/SpringDataSourceConfig.java
new file mode 100644
index 0000000..37de2bb
--- /dev/null
+++ b/druid-spring-boot-samples/src/main/java/com/github/trang/druid/config/SpringDataSourceConfig.java
@@ -0,0 +1,51 @@
+package com.github.trang.druid.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.github.trang.druid.datasource.DruidMultiDataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.context.annotation.Profile;
+
+import javax.sql.DataSource;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 多数据源配置,只在 #{@code spring.profiles.active=dynamic} 时生效
+ *
+ * @author trang
+ */
+@Configuration
+@Profile("dynamic")
+public class SpringDataSourceConfig {
+
+ private static final Logger log = LoggerFactory.getLogger(SpringDataSourceConfig.class);
+
+ @Bean
+ @ConfigurationProperties("spring.datasource.druid.one")
+ public DruidDataSource firstDataSource() {
+ log.debug("druid master-data-source init...");
+ return new DruidMultiDataSource();
+ }
+
+ @Bean
+ @ConfigurationProperties("spring.datasource.druid.two")
+ public DruidDataSource secondDataSource() {
+ log.debug("druid slave-data-source init...");
+ return new DruidMultiDataSource();
+ }
+
+ @Bean
+ @Primary
+ public DynamicDataSource dataSource(DruidDataSource firstDataSource, DruidDataSource secondDataSource) {
+ Map targetDataSources = new HashMap<>();
+ targetDataSources.put("one", firstDataSource);
+ targetDataSources.put("two", secondDataSource);
+ return new DynamicDataSource(firstDataSource, targetDataSources);
+ }
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-samples/src/main/java/com/github/trang/druid/mapper/CityMapper.java b/druid-spring-boot-samples/src/main/java/com/github/trang/druid/mapper/CityMapper.java
index 5adf71c..909acb8 100644
--- a/druid-spring-boot-samples/src/main/java/com/github/trang/druid/mapper/CityMapper.java
+++ b/druid-spring-boot-samples/src/main/java/com/github/trang/druid/mapper/CityMapper.java
@@ -5,11 +5,13 @@ import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
+import java.util.List;
+
@Mapper
public interface CityMapper {
- @Select("select * from city where state = #{state}")
- City findByState(@Param("state") String state);
+ @Select("select * from city")
+ List findAll();
@Select("select * from city where id = #{id}")
City findById(@Param("id") Long id);
diff --git a/druid-spring-boot-samples/src/main/resources/application.yml b/druid-spring-boot-samples/src/main/resources/application.yml
index 357ca2f..8df1e4a 100644
--- a/druid-spring-boot-samples/src/main/resources/application.yml
+++ b/druid-spring-boot-samples/src/main/resources/application.yml
@@ -9,11 +9,14 @@ logging:
com.github.trang: debug
spring:
+ profiles:
+ active: single
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:file:./samples
username: root
password: 123456
+ schema: classpath:/import.sql
druid:
initial-size: 1
min-idle: 1
@@ -55,10 +58,9 @@ spring:
patterns:
- com.github.trang.*
web-stat:
- enabled: true
+ enabled: false
stat-view-servlet:
enabled: true
- schema: classpath:import.sql
transaction:
rollback-on-commit-failure: true
aop:
@@ -66,4 +68,31 @@ spring:
proxy-target-class: true
mybatis:
- type-aliases-package: com.github.trang.druid.model
\ No newline at end of file
+ type-aliases-package: com.github.trang.druid.model
+
+---
+
+debug: true
+
+spring:
+ profiles: single
+
+---
+
+debug: true
+
+spring:
+ profiles: dynamic
+ autoconfigure:
+ exclude:
+ - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
+ datasource:
+ druid:
+ one:
+ name: one
+ max-active: 50
+ max-open-prepared-statements: 50
+ two:
+ name: two
+ max-active: 25
+ max-open-prepared-statements: 25
diff --git a/druid-spring-boot-samples/src/main/resources/import.sql b/druid-spring-boot-samples/src/main/resources/import.sql
index 8c7c7d6..73548bc 100644
--- a/druid-spring-boot-samples/src/main/resources/import.sql
+++ b/druid-spring-boot-samples/src/main/resources/import.sql
@@ -1,10 +1,14 @@
DROP TABLE IF EXISTS city;
CREATE TABLE city (
- id INT(6) PRIMARY KEY AUTO_INCREMENT,
+ id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(64),
- state VARCHAR(32),
- country VARCHAR(32)
+ state VARCHAR(16),
+ country VARCHAR(16)
);
+INSERT INTO city (NAME, state, country) VALUES ('Beijing', 'BJ', 'CN');
+INSERT INTO city (NAME, state, country) VALUES ('Shanghai', 'SH', 'CN');
+INSERT INTO city (NAME, state, country) VALUES ('Guangzhou', 'GZ', 'CN');
+INSERT INTO city (NAME, state, country) VALUES ('Shenzhen', 'SZ', 'CN');
INSERT INTO city (NAME, state, country) VALUES ('San Francisco', 'CA', 'US');
\ No newline at end of file
diff --git a/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/BaseTest.java b/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/BaseTest.java
new file mode 100644
index 0000000..e54510f
--- /dev/null
+++ b/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/BaseTest.java
@@ -0,0 +1,21 @@
+package com.github.trang.druid.test;
+
+import com.github.trang.druid.mapper.CityMapper;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * BaseTest
+ *
+ * @author trang
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public abstract class BaseTest {
+
+ @Autowired(required = false)
+ protected CityMapper cityMapper;
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/DynamicDataSourceTests.java b/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/DynamicDataSourceTests.java
new file mode 100644
index 0000000..95fa223
--- /dev/null
+++ b/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/DynamicDataSourceTests.java
@@ -0,0 +1,58 @@
+package com.github.trang.druid.test;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.github.trang.druid.config.DynamicDataSource;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ActiveProfiles;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * 动态数据源测试
+ *
+ * @author trang
+ */
+@ActiveProfiles("dynamic")
+public class DynamicDataSourceTests extends BaseTest {
+
+ @Autowired
+ private DruidDataSource firstDataSource;
+ @Autowired
+ private DruidDataSource secondDataSource;
+ @Autowired
+ private DynamicDataSource dataSource;
+
+ @Test
+ public void testFirstDataSource() {
+ assertEquals(1, firstDataSource.getInitialSize());
+ assertEquals(1, firstDataSource.getMinIdle());
+ assertEquals(50, firstDataSource.getMaxActive());
+ assertEquals(30000, firstDataSource.getMaxWait());
+ assertEquals(60000, firstDataSource.getTimeBetweenEvictionRunsMillis());
+ assertEquals(300000, firstDataSource.getMinEvictableIdleTimeMillis());
+ assertEquals("SELECT 1", firstDataSource.getValidationQuery());
+ assertEquals(true, firstDataSource.isTestWhileIdle());
+ assertEquals(false, firstDataSource.isTestOnBorrow());
+ assertEquals(false, firstDataSource.isTestOnReturn());
+ assertEquals(50, firstDataSource.getMaxPoolPreparedStatementPerConnectionSize());
+ assertEquals(true, firstDataSource.isUseGlobalDataSourceStat());
+ }
+
+ @Test
+ public void testSecondDataSource() {
+ assertEquals(1, secondDataSource.getInitialSize());
+ assertEquals(1, secondDataSource.getMinIdle());
+ assertEquals(25, secondDataSource.getMaxActive());
+ assertEquals(30000, secondDataSource.getMaxWait());
+ assertEquals(60000, secondDataSource.getTimeBetweenEvictionRunsMillis());
+ assertEquals(300000, secondDataSource.getMinEvictableIdleTimeMillis());
+ assertEquals("SELECT 1", secondDataSource.getValidationQuery());
+ assertEquals(true, secondDataSource.isTestWhileIdle());
+ assertEquals(false, secondDataSource.isTestOnBorrow());
+ assertEquals(false, secondDataSource.isTestOnReturn());
+ assertEquals(25, secondDataSource.getMaxPoolPreparedStatementPerConnectionSize());
+ assertEquals(true, secondDataSource.isUseGlobalDataSourceStat());
+ }
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/MyBatisTests.java b/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/MyBatisTests.java
new file mode 100644
index 0000000..c2c0f85
--- /dev/null
+++ b/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/MyBatisTests.java
@@ -0,0 +1,29 @@
+package com.github.trang.druid.test;
+
+import com.github.trang.druid.model.City;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.List;
+
+/**
+ * MyBatis 测试
+ *
+ * @author trang
+ */
+public class MyBatisTests extends BaseTest {
+
+ @Test
+ public void testOne() {
+ City city = cityMapper.findById(1L);
+ System.out.println(city);
+ }
+
+ @Test
+ public void testAll() {
+ List cities = cityMapper.findAll();
+ System.out.println(cities);
+ Assert.assertEquals(5, cities.size());
+ }
+
+}
\ No newline at end of file
diff --git a/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/DruidTests.java b/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/SingleDataSourceTests.java
similarity index 61%
rename from druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/DruidTests.java
rename to druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/SingleDataSourceTests.java
index de9a92d..c9dec7a 100644
--- a/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/DruidTests.java
+++ b/druid-spring-boot-samples/src/test/java/com/github/trang/druid/test/SingleDataSourceTests.java
@@ -1,33 +1,25 @@
package com.github.trang.druid.test;
import com.alibaba.druid.pool.DruidDataSource;
-import com.alibaba.druid.wall.WallFilter;
-import com.github.trang.druid.mapper.CityMapper;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.context.ActiveProfiles;
import static org.junit.Assert.assertEquals;
/**
+ * 单数据源测试
+ *
* @author trang
*/
-@RunWith(SpringRunner.class)
-@SpringBootTest(webEnvironment = WebEnvironment.NONE)
-public class DruidTests {
+@ActiveProfiles("single")
+public class SingleDataSourceTests extends BaseTest {
@Autowired
private DruidDataSource dataSource;
- @Autowired
- private WallFilter wallFilter;
- @Autowired
- private CityMapper cityMapper;
@Test
- public void testDataSource() {
+ public void testSingleDataSource() {
assertEquals(dataSource.getInitialSize(), 1);
assertEquals(dataSource.getMinIdle(), 1);
assertEquals(dataSource.getMaxActive(), 10);
@@ -42,9 +34,4 @@ public class DruidTests {
assertEquals(dataSource.isUseGlobalDataSourceStat(), true);
}
- @Test
- public void testMybatis() {
- System.out.println(cityMapper.findById(1L));
- }
-
}
\ No newline at end of file
diff --git a/druid-spring-boot-starter/src/main/resources/META-INF/spring.provides b/druid-spring-boot-starter/src/main/resources/META-INF/spring.provides
index cab2686..6e9da6a 100644
--- a/druid-spring-boot-starter/src/main/resources/META-INF/spring.provides
+++ b/druid-spring-boot-starter/src/main/resources/META-INF/spring.provides
@@ -1 +1 @@
-provides: spring-boot-autoconfigure,druid,druid-spring-boot-autoconfigure
\ No newline at end of file
+provides: spring-boot-autoconfigure,spring-jdbc,druid,druid-spring-boot-autoconfigure
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 2d367b6..dafa099 100644
--- a/pom.xml
+++ b/pom.xml
@@ -45,10 +45,11 @@
UTF-8
1.8
+ 4.3.9.RELEASE
1.5.4.RELEASE
1.7.25
3.1.0
- 1.1.0
+ 1.1.1
3.0.1
3.0.0
@@ -79,6 +80,11 @@
spring-boot-configuration-processor
${spring-boot.version}
+
+ org.springframework
+ spring-jdbc
+ ${spring.version}
+
javax.servlet
javax.servlet-api
@@ -126,6 +132,7 @@
maven-surefire-plugin
${maven-surefire-plugin.version}
+ true
true
@@ -141,11 +148,13 @@
org.eluder.coveralls
coveralls-maven-plugin
${coveralls-maven-plugin.version}
+ true
org.codehaus.mojo
cobertura-maven-plugin
${cobertura-maven-plugin.version}
+ true
xml
256m
@@ -165,6 +174,7 @@
maven-javadoc-plugin
${maven-javadoc-plugin.version}
+ true
package
@@ -181,6 +191,7 @@
maven-gpg-plugin
${maven-gpg-plugin.version}
+ true
verify
@@ -193,6 +204,7 @@
maven-deploy-plugin
${maven-deploy-plugin.version}
+ true
true
@@ -200,6 +212,7 @@
maven-release-plugin
${maven-release-plugin.version}
+ true
true
true
@@ -219,10 +232,12 @@
maven-dependency-plugin
${maven-dependency-plugin.version}
+ true
maven-enforcer-plugin
${maven-enforcer-plugin.version}
+ true
enforce-maven
@@ -242,10 +257,12 @@
maven-clean-plugin
${maven-clean-plugin.version}
+ true
maven-resources-plugin
${maven-resources-plugin.version}
+ true
${project.build.sourceEncoding}
@@ -253,6 +270,7 @@
maven-compiler-plugin
${maven-compiler-plugin.version}
+ true
${project.build.sourceEncoding}
${java.version}
@@ -262,6 +280,7 @@
maven-surefire-plugin
${maven-surefire-plugin.version}
+ true
**/com/github/trang/**/test/junit/**Test.java
@@ -271,10 +290,12 @@
maven-jar-plugin
${maven-jar-plugin.version}
+ true
maven-source-plugin
${maven-source-plugin.version}
+ true
package
@@ -287,6 +308,7 @@
maven-install-plugin
${maven-install-plugin.version}
+ true