1:yml 配置
spring:
datasource:
dynamic:
datasource:
master:
url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
second-datasource:
url: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
2:必须pom依赖配
<!-- 动态数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
2-1:不要加入一下依赖不然会报以下错误
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
<scope>runtime</scope>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
2-2:当出现以上错误可以在yml配置文件去掉DruidDataSourceAutoConfigure,如下
spring:
autoconfigure:
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
3:加入数据库连接池druid依赖管理(使用多数据源一定要用链接池),Druid是阿里巴巴开源的一个数据库连接池和实时数据分析组件。相比其他连接池,Druid在功能特性、性能、监控等方面有很多优势,比如支持SQL解析、慢SQL日志、提供多维度监控等
spring:
autoconfigure:
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
datasource:
druid:
stat-view-servlet:
enabled: true
loginUsername: admin
loginPassword: 123456
allow:
web-stat-filter:
enabled: true
dynamic:
druid: # 全局druid参数,绝大部分值和默认保持一致。(现已支持的参数如下,不清楚含义不要乱设置)
# 连接池的配置信息
# 初始化大小,最小,最大
initial-size: 5
min-idle: 5
maxActive: 20
# 配置获取连接等待超时的时间r
maxWait: 60000
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
datasource:
master:
url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
second:
url: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
3-1:加入依赖
<!-- 动态数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.6</version>
</dependency>
Druid连接池的自动配置类是DruidDataSourceAutoConfigure类上有一行注解
@EnableConfigurationProperties({DruidStatProperties.class, DataSourceProperties.class})
@EnableConfigurationProperties注解的作用是:使配置文件中的配置生效并且映射到指定类的属性
DruidStatProperties:指定的前缀是spring.datasource.druid,主要设置连接池的一些参数
DataSourceProperties:指定的前缀是spring.datasource,主要设置url,username,password等信息
3-2:DruidConfig 配置类
package com.example.poi.config;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import java.io.IOException;
/**
* @Description: DruidConfig配置类
*/
@Configuration
@AutoConfigureAfter(DruidDataSourceAutoConfigure.class)
public class DruidConfig {
/**
* 带有广告的common.js全路径,druid-1.1.14
*/
private static final String FILE_PATH = "support/http/resources/js/common.js";
/**
* 原始脚本,触发构建广告的语句
*/
private static final String ORIGIN_JS = "this.buildFooter();";
/**
* 替换后的脚本
*/
private static final String NEW_JS = "//this.buildFooter();";
/**
* 去除Druid监控页面的广告
*
* @param properties DruidStatProperties属性集合
* @return {@link FilterRegistrationBean}
*/
@Bean
@ConditionalOnWebApplication
@ConditionalOnProperty(name = "spring.datasource.druid.stat-view-servlet.enabled", havingValue = "true")
public FilterRegistrationBean<RemoveAdFilter> removeDruidAdFilter(
DruidStatProperties properties) throws IOException {
// 获取web监控页面的参数
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
// 提取common.js的配置路径
String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
// 获取common.js
String text = Utils.readFromResource(FILE_PATH);
// 屏蔽 this.buildFooter(); 不构建广告
final String newJs = text.replace(ORIGIN_JS, NEW_JS);
FilterRegistrationBean<RemoveAdFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new RemoveAdFilter(newJs));
registration.addUrlPatterns(commonJsPattern);
return registration;
}
/**
* 删除druid的广告过滤器
*
* @author BBF
*/
private class RemoveAdFilter implements Filter {
private final String newJs;
public RemoveAdFilter(String newJs) {
this.newJs = newJs;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
// 重置缓冲区,响应头不会被重置
response.resetBuffer();
response.getWriter().write(newJs);
}
}
}
4:配置动态数据源方法二,yml随意配置或者通过配置类生成数据库链接
4-1:yml配置(记得配置数据库链接池)
datasource:
master:
url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
second:
url: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
4-2:配置动态源数据类
@Configuration
public class DatabaseConfig {
@Value("${datasource.master.url}")
private String dataSourceUrl;
@Value("${datasource.master.username}")
private String dataSourceUsername;
@Value("${datasource.master.password}")
private String dataSourcePassword;
@Value("${datasource.master.driver-class-name}")
private String dataSourceDriverClassName;
@Value("${datasource.second.url}")
private String dataSourceUrl2;
@Value("${datasource.second.username}")
private String dataSourceUsername2;
@Value("${datasource.second.password}")
private String dataSourcePassword2;
@Value("${datasource.second.driver-class-name}")
private String dataSourceDriverClassName2;
public DataSource dataSource() {
return DataSourceBuilder.create()
.url(dataSourceUrl)
.username(dataSourceUsername)
.password(dataSourcePassword)
.driverClassName("com.mysql.cj.jdbc.Driver")
.build();
}
public DataSource dataSource2() {
return DataSourceBuilder.create()
.url(dataSourceUrl2)
.username(dataSourceUsername2)
.password(dataSourcePassword2)
.driverClassName("com.mysql.cj.jdbc.Driver")
.build();
}
// 添加动态数据源
@Bean
public DynamicRoutingDataSource dynamicDataSource() {
DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
dynamicRoutingDataSource.addDataSource("master", dataSource());
dynamicRoutingDataSource.addDataSource("two", dataSource2());
return dynamicRoutingDataSource;
}
}
4-3:在server服务层通过@DS调用
@Override
@DS("two")
public List<EntityDemo> testSql(Page<EntityDemo> pageList, String id) {
List<EntityDemo> entityDemos = entityDemoMapper.testSql(pageList, id);
DynamicDataSourceContextHolder.clear();
return entityDemos;
4-4:可以在启动类观察动态数据源情况如下:run.getBean(DataSource.class).getConnection();
@SpringBootApplication
@MapperScan(basePackages = "com.example.poi.mapper")
public class PoiApplication {
public static void main(String[] args) {
ConfigurableApplicationContext run = SpringApplication.run(PoiApplication.class, args);
// 检查数据库连接是否正常
try {
// 获取DataSource bean,并调用getConnection()方法测试连接
run.getBean(javax.sql.DataSource.class).getConnection();
System.out.println("数据库连接正常!");
} catch (Exception e) {
System.err.println("数据库连接异常:" + e.getMessage());
// 处理连接异常的逻辑
}
}
}
5:方法三配置动态数据源使,使用注解的方式(推荐使用)
5-1:yml配置
spring:
datasource:
master:
jdbcUrl: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
second:
jdbcUrl: jdbc:mysql://192.168.11.50:3306/commons_utils?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
username: root
password: root
driverClassName: com.mysql.cj.jdbc.Driver
druid:
#连接池初始化时创建的数据库连接数量
initial-size: 10
#连接池中保持最小的空闲连接数量。如果空闲连接数量少于这个值,连接池会创建新的连接来补充
min-idle: 5
#
max-active: 80
#配置获取链接等待超时的时间
max-wait:
type: com.alibaba.druid.pool.DruidDataSource
5-2:配置动态源数据类(在需要切换的地方使用@DS就可以),整合mybatis-plus的过程中,我们还需要创建动态数据源的SqlSessionFactory,如果我们想要实现动态数据源切换,则需要手动配置SqlSessionFactory,以便于它使用动态数据源,同理事务管理器也需要重新配置:
@Configuration
public class DatabaseConfig {
@Bean("one")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}
@Bean("two")
@ConfigurationProperties(prefix = "spring.datasource.second")
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
//添加动态数据源
@Bean
public DynamicRoutingDataSource dynamicDataSource(@Qualifier("one") DataSource dataSource, @Qualifier("two") DataSource dataSource2) {
DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
dynamicRoutingDataSource.addDataSource("master", dataSource);
dynamicRoutingDataSource.addDataSource("two", dataSource2);
return dynamicRoutingDataSource;
}
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean(DynamicRoutingDataSource dynamicRoutingDataSource) throws Exception {
//使用SqlSessionFactoryBean不可以正常使用 BaseMapper的MyBatis通用的CRUD
//SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
sessionFactory.setDataSource(dynamicRoutingDataSource);
return sqlSessionFactoryBean.getObject();
}
/**
* 重写事务管理器,管理动态数据源
*/
@Primary
@Bean(value = "transactionManager")
public PlatformTransactionManager annotationDrivenTransactionManager(DynamicRoutingDataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
5-3:切换使用数据源
文章来源:https://www.toymoban.com/news/detail-695852.html
6:方法四配置动态数据源使用,使用注解的方式(推荐使用)
6-1:添加注解和切面
package com.example.poi.minds.annotation;
import java.lang.annotation.*;
/**
* @Author xu
* @create 2023/9/7 22
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MinDS {
/**
* groupName or specific database name or spring SPEL name.
*
* @return the database you want to switch
*/
String value() default "";
}
package com.example.poi.minds.aop;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.example.poi.config.DataSourceHolder;
import com.example.poi.desensitization.annotation.SensitiveDecode;
import com.example.poi.desensitization.annotation.SensitiveEncode;
import com.example.poi.desensitization.utils.SensitiveInfoUtil;
import com.example.poi.minds.annotation.MinDS;
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.List;
/**
* @Author xu
* @create 2023/9/7 22
*/
@Slf4j
@Aspect
@Component
public class MinDSAspect {
/**
* 定义切点Pointcut
*/
@Pointcut("@annotation(com.example.poi.minds.annotation.MinDS) ")
public void dsPointCut() {
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 处理结果
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
MinDS minDS = method.getAnnotation(MinDS.class);
String value = minDS.value();
if (StringUtils.isBlank(value)) {
return null;
}
DataSourceHolder.setDataSource(value);
try {
return joinPoint.proceed();
} finally {
DataSourceHolder.clearDataSource();
}
}
}
文章来源地址https://www.toymoban.com/news/detail-695852.html
6-2:动态数据源简单的说就是能够自由切换的数据源,Spring提供了一个抽象类AbstractRoutingDataSource,我们只需要extends ,并且重写determineCurrentLookupKey()即可determineCurrentLookupKey()的作用:返回需要切换的数据源的key,然后根据这个key获取对应的数据源信息
package com.example.poi.config;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @Author xu
* @create 2023/9/7 22
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
/**
* 返回需要使用的数据源key,将会按照这个key从Map中获取对应的数据源(切换)
* @return
*/
@Override
protected Object determineCurrentLookupKey() {
//从ThreadLocal中取出key
return DataSourceHolder.getDataSource();
}
}
6-3:单独封装一个类:DataSourceHolder,在多线程的情况下,数据源切换如何保证线程隔离呢?,我们不能这边切换了影响了其他线程的执行,这里我们便想到了ThreadLocal
package com.example.poi.config;
/**
* @Author xu
* @create 2023/9/7 20
*/
/**
* 线程安全类:使用ThreadLocal存储切换数据源后的KEY
*/
public class DataSourceHolder {
/**
* 线程ThreadLocal
*/
private static final ThreadLocal<String> dataSources = new InheritableThreadLocal();
/**
* 设置数据源
* @param datasource
*/
public static void setDataSource(String datasource) {
dataSources.set(datasource);
}
/**
* 获取数据源
* @return
*/
public static String getDataSource() {
return dataSources.get();
}
/**
* 清除数据源
*/
public static void clearDataSource() {
dataSources.remove();
}
}
到了这里,关于yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!