一、引入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

Springboot+Druid 动态数据源配置监控的更多相关文章

  1. Druid动态数据源配置

    上文已经讲了单个数据源的Druid的配置(http://www.cnblogs.com/nbfujx/p/7686634.html) Druid动态数据源配置 主要是继承AbstractRouting ...

  2. Spring Boot2.x 动态数据源配置

    原文链接: Spring Boot2.x 动态数据源配置 基于 Spring Boot 2.x.Spring Data JPA.druid.mysql 的动态数据源配置Demo,适合用于数据库的读写分 ...

  3. 基于springboot的多数据源配置

    发布时间:2018-12-11   技术:springboot1.5.1 + maven3.0.1+ mybatis-plus-boot-starter2.3.1 + dynamic-datasour ...

  4. springboot+ibatis 多数据源配置

    这个是boot基本版本包,因为我用的打包方式是war所以去除掉了boot内置的tomcat,但是为了方便测试又引入了内置tomcat,只要添加<scope>provided</sco ...

  5. (七)spring+druid多数据源配置

    druid多数据源配置 一.druid简介 Druid首先是一个数据库连接池,但它不仅仅是一个数据库连接池,它还包含一个ProxyDriver,一系列内置的JDBC组件库,一个SQL Parser. ...

  6. springboot+druid连接池及监控配置

    1. 问题描述 阿里巴巴的数据库连接池Druid在效率与稳定性都很高,被很多开发团队使用,并且自带的Druid监控也很好用,本章简单介绍下springboot+druid配置连接池及监控. 2. 解决 ...

  7. spring boot +mybatis+druid 多数据源配置

    因为我的工程需要在两个数据库中操作数据,所以要配置两个数据库,我这里没有数据源没有什么主从之分,只是配合多数据源必须要指定一个主数据源,所以我就把 操作相对要对的那个数据库设置为主数据(dataBas ...

  8. Mybatis+Druid多数据源配置

    在日常开发中我们可能会用到多数据源开发,什么是多数据源? 简单来讲的话,就是一个项目连接多个数据库.当然只是可能会用到,我暂时没见过应用场景,但是还是了解学习一下 此项目可以基于上一个简单集成项目进行 ...

  9. SpringBoot 的多数据源配置

    最近在项目开发中,需要为一个使用 MySQL 数据库的 SpringBoot 项目,新添加一个 PLSQL 数据库数据源,那么就需要进行 SpringBoot 的多数据源开发.代码很简单,下面是实现的 ...

随机推荐

  1. Hibernate框架使用之环境搭建

    第一步:引入所需的jar包 第二步:创建实体类,配置实体类与数据表的映射关系 创建实体类 User.java package cn.hao.entity; public class User { /* ...

  2. HGAME2021 week4 pwn writeup

    第四周只放出两道题,也不是很难. house_of_cosmos 没开pie,并且可以打got表. 在自写的输入函数存在漏洞.当a2==0时,因为时int类型,这里就会存在溢出.菜单题,但是没有输出功 ...

  3. Python3 中bytes数据类型深入理解(ASCII码对照表)

    bytes的来源 bytes 是 Python 3.x 新增的类型,在 Python 2.x 中是不存在的. bytes 的意思是"字节",以字节为单位存储数据.而一个字节二进制为 ...

  4. libevent源码学习(17):缓冲管理框架

    目录Libevent缓冲区类型Libevent缓冲区结构缓冲区的读出与写入缓冲区的读入与写出缓冲区水位机制缓冲区回调机制延迟回调机制Libevent缓冲区类型       Libevent中提供了多种 ...

  5. c++之记一次常见数据类型在fedora和wind10下所占的长度

    包括: char , int , float, double, long ,long long , unsigned long long , long double 1.源码 #include < ...

  6. 【LeetCode】1071. Greatest Common Divisor of Strings 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力遍历 日期 题目地址:https://leetc ...

  7. 【剑指Offer】孩子们的游戏(圆圈中最后剩下的数) 解题报告(Python)

    [剑指Offer]孩子们的游戏(圆圈中最后剩下的数) 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-in ...

  8. 【LeetCode】673. Number of Longest Increasing Subsequence 解题报告(Python)

    [LeetCode]673. Number of Longest Increasing Subsequence 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https:/ ...

  9. P1629八

    P1629八 Accepted 标签:[显示标签]     描述 八是个很有趣的数字啊.八=发,八八=爸爸,88=拜拜.当然最有趣的还是8用二进制表示是1000.怎么样,有趣吧.当然题目和这些都没有关 ...

  10. Windows服务注册(需要指定config文件的情况下)

    最近,遇到一个问题:需要将telegraf在Win平台下注册为windows服务(避免误操作关闭CMD窗口): 尝试了网上的几种注册Windows服务的方法,发现无法将telegraf这种需要在CMD ...