SpringBoot2.0.5 + jpa + druid 多数据源 数据库密码加密
作者:互联网
SpringBoot2.0.5 + jpa + druid 多数据源 数据库密码加密
文章目录
- SpringBoot2.0.5 + jpa + druid 多数据源 数据库密码加密
- 一、druid 多数据源
- 4.设置DataSource
- 5.数据源设置
- 7.需要注意的坑
- 二.数据库密码加密
- 参考文章
一、druid 多数据源
1. pom.xml
建议使用1.1.10以上版本
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- 若项目本来用了logback 可以不引入,设置filters 为slf4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- sqlserver数据库连接 -->
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<scope>runtime</scope>
</dependency>
<!-- mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.21</version>
<scope>runtime</scope>
</dependency>
<!--用于读取配置-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
2.配置文件 application.properties
#druid的一些基本配置
spring.datasource.druid.default.initialSize = 5
spring.datasource.druid.default.minIdle = 5
spring.datasource.druid.default.maxActive = 30
spring.datasource.druid.default.maxWait = 1200000
spring.datasource.druid.default.timeBetweenEvictionRunsMillis = 1200000
spring.datasource.druid.default.minEvictableIdleTimeMillis = 300000
spring.datasource.druid.default.primary-validationQuery = SELECT 'x'
spring.datasource.druid.default.secondary-validationQuery = SELECT 1
spring.datasource.druid.default.testWhileIdle = true
spring.datasource.druid.default.testOnBorrow = false
spring.datasource.druid.default.testOnReturn = false
spring.datasource.druid.default.poolPreparedStatements = true
spring.datasource.druid.default.maxPoolPreparedStatementPerConnectionSize = 30
spring.datasource.druid.primary.filters=stat,wall,slf4j
spring.datasource.druid.default.connectionProperties = druid.stat.mergeSql=false;druid.stat.slowSqlMillis=5000
spring.aop.proxy-target-class = true
# merge multi DruidDataSource Data
spring.datasource.druid.default.useGlobalDataSourceStat = true
# 主数据源
spring.datasource.druid.primary.url=jdbc:sqlserver://xxx:1433;DatabaseName=xxx
spring.datasource.druid.primary.username=xxx
spring.datasource.druid.primary.password=xxx
spring.datasource.druid.primary.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.druid.primary.primary-dialect=org.hibernate.dialect.SQLServer2012Dialect
# 部分sql由于wall查询存在错误
spring.datasource.druid.primary.filters=
# 第二数据源 mysql
spring.datasource.druid.secondary.url=jdbc:mysql://xxx:3306/xxx?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
spring.datasource.druid.secondary.username=xxx
spring.datasource.druid.secondary.password=xxx
spring.datasource.druid.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.druid.secondary.primary-dialect=org.hibernate.dialect.MySQLDialect
3.DruidDefaultPropertiesConfig 用于接收通用的druid配置
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "spring.datasource.druid.default")
public class DruidDefaultPropertiesConfig {
private int initialSize;
private int minIdle;
private int maxActive;
private int maxWait;
private int timeBetweenEvictionRunsMillis;
private int minEvictableIdleTimeMillis;
private String validationQuery;
private boolean testWhileIdle;
private boolean testOnBorrow;
private boolean testOnReturn;
private boolean poolPreparedStatements;
private int maxPoolPreparedStatementPerConnectionSize;
private String filters;
private String connectionProperties;
private boolean useGlobalDataSourceStat;
}
4.设置DataSource
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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 javax.sql.DataSource;
import javax.xml.crypto.Data;
import java.sql.SQLException;
@Configuration
public class DruidDataSourceConfig {
@Autowired
DruidDefaultPropertiesConfig druidDefaultPropertiesConfig;
@Primary
@Qualifier("primaryDataSource")
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.primary")
public DataSource primaryDataSource() {
return getDruidDataSource();
}
@Qualifier("secondaryDataSource")
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.druid.secondary")
public DataSource secondaryDataSource() {
return getDruidDataSource();
}
private DruidDataSource getDruidDataSource() {
DruidDataSource datasource = DruidDataSourceBuilder.create().build();
datasource.setInitialSize(druidDefaultPropertiesConfig.getInitialSize());
datasource.setMinIdle(druidDefaultPropertiesConfig.getMinIdle());
datasource.setMaxActive(druidDefaultPropertiesConfig.getMaxActive());
datasource.setMaxWait(druidDefaultPropertiesConfig.getMaxWait());
datasource.setTimeBetweenEvictionRunsMillis(druidDefaultPropertiesConfig.getTimeBetweenEvictionRunsMillis());
datasource.setMinEvictableIdleTimeMillis(druidDefaultPropertiesConfig.getMinEvictableIdleTimeMillis());
datasource.setValidationQuery(druidDefaultPropertiesConfig.getValidationQuery());
datasource.setTestWhileIdle(druidDefaultPropertiesConfig.isTestWhileIdle());
datasource.setTestOnBorrow(druidDefaultPropertiesConfig.isTestOnBorrow());
datasource.setTestOnReturn(druidDefaultPropertiesConfig.isTestOnReturn());
datasource.setPoolPreparedStatements(druidDefaultPropertiesConfig.isPoolPreparedStatements());
datasource.setMaxPoolPreparedStatementPerConnectionSize(druidDefaultPropertiesConfig.getMaxPoolPreparedStatementPerConnectionSize());
datasource.setUseGlobalDataSourceStat(druidDefaultPropertiesConfig.isUseGlobalDataSourceStat());
try {
datasource.setFilters(druidDefaultPropertiesConfig.getFilters());
} catch (SQLException e) {
System.err.println("druid configuration initialization filter: "+ e);
}
datasource.setConnectionProperties(druidDefaultPropertiesConfig.getConnectionProperties());
return datasource;
}
}
5.数据源设置
第一数据源
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.Map;
@Configuration
@EnableTransactionManagement
//设置Repository所在位置
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactoryPrimary",
transactionManagerRef="transactionManagerPrimary",
basePackages= { "xx.repository",
"xx.xx.repository",
"xx.xx.repository" })
public class PrimaryConfig {
@Autowired
@Qualifier("primaryDataSource")
private DataSource primaryDataSource;
@Autowired
private JpaProperties jpaProperties;
@Primary
@Bean(name = "entityManagerPrimary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
@Primary
@Bean(name = "entityManagerFactoryPrimary")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary (EntityManagerFactoryBuilder builder) {
//设置实体类位置
String[] packages = new String[]{
"xxx.domain",
"xxx.domain",
};
LocalContainerEntityManagerFactoryBean entityManagerFactory = builder
.dataSource(primaryDataSource)
.packages(packages)
.properties(getVendorProperties())
.persistenceUnit("primaryPersistenceUnit")
.build();
return entityManagerFactory;
}
@Value("${spring.datasource.druid.primary.primary-dialect}")
private String primaryDialect;
private Map<String, Object> getVendorProperties() {
Map<String, Object> properties = jpaProperties.getHibernateProperties(new HibernateSettings());
properties.put("hibernate.dialect",primaryDialect);
return properties;
}
@Primary
@Bean(name = "transactionManagerPrimary")
public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
第二数据源
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManager;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
@EnableTransactionManagement
//设置Repository所在位置
@EnableJpaRepositories(
entityManagerFactoryRef="entityManagerFactorySecondary",
transactionManagerRef="transactionManagerSecondary",
basePackages= { "xx.repository" })
public class SecondaryConfig {
@Autowired
@Qualifier("secondaryDataSource")
private DataSource secondaryDataSource;
@Autowired
private JpaProperties jpaProperties;
@Bean(name = "entityManagerSecondary")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryPrimary(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactorySecondary")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryPrimary(EntityManagerFactoryBuilder builder) {
//设置实体类位置
String[] packages = new String[]{"xxx.domain"};
LocalContainerEntityManagerFactoryBean entityManagerFactory = builder
.dataSource(secondaryDataSource)
.packages(packages)
.properties(getVendorProperties())
.persistenceUnit("secondaryPersistenceUnit")
.build();
entityManagerFactory.setJpaPropertyMap(jpaProperties.getProperties());
return entityManagerFactory;
}
@Value("${spring.datasource.druid.secondary.primary-dialect}")
private String secondaryDialect;
private Map<String, Object> getVendorProperties() {
Map<String, Object> properties = jpaProperties.getHibernateProperties(new HibernateSettings());
properties.put("hibernate.dialect",secondaryDialect);
return properties;
}
@Bean(name = "transactionManagerSecondary")
public PlatformTransactionManager transactionManagerPrimary(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryPrimary(builder).getObject());
}
}
需要注意这里是springboot 2.0.X的写法
其他写法参考 文章 未验证
SpringBoot 1.5.x 需要修改getVendorPropertiest方法
private Map<String, String> getVendorProperties() {
return jpaProperties.getHibernateProperties(userDataSource);
}
springBoot2.1的写法
private Map<String, Object> getVendorProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
7.需要注意的坑
1.不同类型数据库需要设置hibernate.dialect ,需要根据数据库版本设置
2.spring.datasource.druid.primary.filters=stat,wall,slf4j 原来项目中有一些sql由于设置了wall ,查询报错,目前只能去掉wall的设置
二.数据库密码加密
1. 使用druid密码加密
使用druid jar加密,获取到publickey和password
java -cp druid-1.0.16.jar com.alibaba.druid.filter.config.ConfigTools you_password
解密类
import com.alibaba.druid.filter.config.ConfigTools;
import com.alibaba.druid.util.DruidPasswordCallback;
public class DesPassword extends DruidPasswordCallback {
public static void main(String[] args) throws Exception{
String publickey = "";
String password = "";
String pwd = ConfigTools.decrypt(publickey, password);
System.out.println(pwd);
}
}
修改配置文件
# 公钥
secondary.publickey=${spring.datasource.druid.secondary.publickey}
# 配置 connection-properties,启用加密,配置公钥。
spring.datasource.druid.secondary.connection-properties=config.decrypt=true;config.decrypt.key=${secondary.publickey};druid.stat.mergeSql=false;druid.stat.slowSqlMillis=5000
# 启动ConfigFilter
spring.datasource.druid.secondary.filters=stat,wall,slf4j,config
其中spring.datasource.druid.secondary.publickey 设置到jvm中,避免暴露
#idea中
-Dspring.datasource.druid.secondary.publickey=
#Java启动
java -jar xxx.jar --spring.datasource.druid.secondary.publickey=
2.使用Jasypt 加密
增加依赖
<!-- jasypt -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
配置
# 加密盐值
jasypt.encryptor.password=abc
# 加密算法设置 3.0.0 以后
jasypt.encryptor.algorithm=PBEWithMD5AndDES
jasypt.encryptor.iv-generator-classname=org.jasypt.iv.NoIvGenerator
加密盐值不建议配置在配置文件
#设置jvm
-Djasypt.encryptor.password=abc
#java
java -jar xx.jar --jasypt.encryptor.password=abc
工具类加密解密
import org.jasypt.util.text.BasicTextEncryptor;
import org.junit.Test;
public class JasyptUtil {
@Test
public void jasyptTest() {
BasicTextEncryptor encryptor = new BasicTextEncryptor();
// application.properties, jasypt.encryptor.password
encryptor.setPassword("abc");
// encrypt root
System.out.println(encryptor.encrypt("1234"));
System.out.println(encryptor.decrypt(""));
}
}
配置密码
spring.datasource.druid.primary.password=ENC(加密后密码)
参考文章
Spring Boot Jpa多数据源配置
SpringBoot敏感配置加密:Druid
jasypt:
数据库密码配置项都不加密?心也太大了吧!
在Springboot中通过jasypt 进行加密解密
SpringBoot 集成 Jasypt 对数据库加密以及踩坑的记录分享
标签:SpringBoot2.0,jpa,数据源,org,druid,springframework,datasource,spring,import 来源: https://blog.csdn.net/jiea201611/article/details/113766834