一、引入maven依賴,使用 starter 與原生 druid 依賴配置有所不同
<dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.8</version> </dependency>
二、配置數據源
spring:
datasource:
druid:
filter:
stat: #開啟sql監控
enabled: true
wall:
enabled: true
slf4j:
enabled: true
DB1:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:sqlserver://127.0.0.1:1487;DatabaseName=CN2018
username: root
password: 12345
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# 連接池的配置信息
initial-size: 5
min-idle: 5
maxActive: 20
maxWait: 60000 # 配置獲取連接等待超時的時間
timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒
minEvictableIdleTimeMillis: 300000 # 配置一個連接在池中最小生存的時間,單位是毫秒
# validationQuery: SELECT 1 FROM DUAL # mysql數據庫
validationQuery: SELECT 1 # sqlserver 數據庫
poolPreparedStatements: true # 打開PSCache,並且指定每個連接上PSCache的大小
maxPoolPreparedStatementPerConnectionSize: 20
DB2:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:sqlserver://127.0.0.1:1488;DatabaseName=DB2022
username: root
password: 123456
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
# 連接池的配置信息
initial-size: 1
min-idle: 1
maxActive: 5
maxWait: 60000 # 配置獲取連接等待超時的時間
timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒
minEvictableIdleTimeMillis: 300000 # 配置一個連接在池中最小生存的時間,單位是毫秒
# validationQuery: SELECT 1 FROM DUAL # mysql數據庫
validationQuery: SELECT 1 # sqlServer 數據庫
poolPreparedStatements: true # 打開PSCache,並且指定每個連接上PSCache的大小
maxPoolPreparedStatementPerConnectionSize: 20
三、創建配置類
//記錄數據庫名 public interface ContextConst { enum DataSourceType{ DB1,DB2 } }
//數據源持有類 @Slf4j public class DataSourceContextHolder { /** * CONTEXT_HOLDER代表一個可以存放String類型的ThreadLocal對象, * 此時任何一個線程可以並發訪問這個變量, * 對它進行寫入、讀取操作,都是線程安全的。 * 比如一個線程通過CONTEXT_HOLDER.set(“aaaa”);將數據寫入ThreadLocal中, * 在任何一個地方,都可以通過CONTEXT_HOLDER.get();將值獲取出來。 * 這里寫入的就是數據庫名, */ private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); public static void setDataSource(String dbType){ CONTEXT_HOLDER.set(dbType); } public static String getDataSource(){ return CONTEXT_HOLDER.get(); } public static void clearDataSource(){ CONTEXT_HOLDER.remove(); } }
//數據源路由實現類 public class DynamicDataSource extends AbstractRoutingDataSource { /** * @Description:數據源路由實現類 AbstractRoutingDataSource(每執行一次數據庫 , 動態獲取DataSource) */ @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSource(); } }
//自定義切換數據源注解 @Target({ElementType.TYPE,ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface TargetDateSouce { ContextConst.DataSourceType value() default ContextConst.DataSourceType.DB1; }
//AOP動態數據源通知 @Component @Aspect @Order(-1) //保證在@Transactional之前執行,必須加上,不然無法分辨是哪個數據源在執行事務 @Slf4j public class DynamicDataSourceAspect { @Before("execution(* com.blaze.pboc.service..*.*(..))") public void before(JoinPoint point) { try { TargetDateSouce annotationOfClass = point.getTarget().getClass().getAnnotation(TargetDateSouce.class); String methodName = point.getSignature().getName(); Class[] parameterTypes = ((MethodSignature) point.getSignature()).getParameterTypes(); Method method = point.getTarget().getClass().getMethod(methodName, parameterTypes); TargetDateSouce methodAnnotation = method.getAnnotation(TargetDateSouce.class); methodAnnotation = methodAnnotation == null ? annotationOfClass : methodAnnotation; ContextConst.DataSourceType dataSourceType = methodAnnotation != null && methodAnnotation.value() != null ? methodAnnotation.value() : ContextConst.DataSourceType.DB1; DataSourceContextHolder.setDataSource(dataSourceType.name()); } catch (NoSuchMethodException e) { log.error("error", e); } } @After("execution(* com.blaze.pboc.service..*.*(..))") public void after(JoinPoint point) { DataSourceContextHolder.clearDataSource(); } }
//動態數據源配置類 @SpringBootConfiguration public class DruidDataSourceConfig { @Bean @ConfigurationProperties(prefix = "spring.datasource.druid.db1") public DruidDataSource masterDataSource() { return DruidDataSourceBuilder.create().build(); } @Bean @ConfigurationProperties(prefix = "spring.datasource.druid.db2") public DruidDataSource clusterDataSource() { DruidDataSource druidDataSource = DruidDataSourceBuilder.create().build(); return druidDataSource; } @Primary @Bean public DataSource dynamicDataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); //配置默認數據源 dynamicDataSource.setDefaultTargetDataSource(masterDataSource()); //配置多數據源這里的key一定要是string類型,枚舉類型並不支持,所以用到枚舉中name()方法轉成string,或者用toString方法。 HashMap<Object, Object> dataSourceMap = new HashMap(); dataSourceMap.put(ContextConst.DataSourceType.DB1.name(), masterDataSource()); dataSourceMap.put(ContextConst.DataSourceType.DB2.name(), clusterDataSource()); dynamicDataSource.setTargetDataSources(dataSourceMap); return dynamicDataSource; } // 配置@Transactional注解事務 @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dynamicDataSource()); } //配置 Druid 監控管理后台的Servlet; //內置 Servlet 容器時沒有web.xml文件,所以使用 Spring Boot 的注冊 Servlet 方式 @Bean public ServletRegistrationBean registrationBean() { ServletRegistrationBean<StatViewServlet> bean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); Map<String, String> initParameters = new HashMap<>(); initParameters.put("loginUsername", "admin"); initParameters.put("loginPassword", "12345"); bean.setInitParameters(initParameters); return bean; } //去除Druid監控頁面的廣告 @Bean public FilterRegistrationBean removeDruidAdFilter() throws IOException { String text = Utils.readFromResource("support/http/resources/js/common.js"); final String newJs = text.replace("this.buildFooter();", ""); // 新建一個過濾器注冊器對象 FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>(); // 注冊common.js文件的過濾器 registration.addUrlPatterns("/druid/js/common.js"); // 添加一個匿名的過濾器對象,並把改造過的common.js文件內容寫入到瀏覽器 registration.setFilter((servletRequest, servletResponse, filterChain) -> { // 重置緩沖區,響應頭不會被重置 servletResponse.resetBuffer(); // 把改造過的common.js文件內容寫入到瀏覽器 servletResponse.getWriter().write(newJs); }); return registration; } }
四、測試,常用的數據源配置db1,無需添加注解
五、登陸 web 監控端
http://127.0.0.1:9000/api/druid/login.html