本文介绍了基于Spring Boot的MySQL数据源配置实现。
主要内容包括:
1)通过application.yml配置MySQL连接参数,包括加密密码处理;
2)定义MysqlDatasourceConfig类实现Druid数据源配置,包含连接池参数设置;
3)主应用类Dbapi集成Eureka、Feign等服务;
4)JavaConfig类处理配置解密和日志记录。
该实现采用Druid连接池,支持加密密码自动解密,并提供了完善的连接池参数配置,适用于分布式微服务环境下的数据库连接管理。
本文详细介绍了基于SpringBoot和Druid的MySQL数据源配置方案。通过application.yml文件配置数据库连接参数,采用AES加密存储密码,配置类自动完成解密。核心实现包括:1)MysqlDatasourceConfig类配置Druid连接池参数;2)主应用Dbapi集成Eureka、Feign等微服务组件;3)JavaConfig类处理密码解密和日志记录。该方案支持连接池参数优化,如最大等待时间、初始连接数等配置,并提供了完善的MyBatis集成。加密模块采用Hutool工具实现AES加解密,确保敏感数据安全。整体架构适用于分布式微服务环境,兼顾安全性和性能。
配置:
spring: initializer: enabled: true batch: initializeSchema: always job: enabled: false datasource: mysql: enabled: true testWhileIdle: true driverClassName: com.mysql.cj.jdbc.Driver url: jdbc:mysql://${MYSQL_HOST:huawei.akunlong.top:13306}/platform?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull username: ${MYSQL_USER:root} password: ${MYSQL_PASSWORD:enc(LZXHOEwmmclHHip7QkVl3YQebNO4uNQJONS3usFEyMc=)} maxWait: 15000 initialSize: 5 minIdle: 2 testOnBorrow: false validationQuery: SELECT 1
数据源定义
@Configuration @Slf4j @Data @Primary @ConditionalOnProperty(prefix = "spring.datasource.mysql", name = "enabled", havingValue = "true") @MapperScan(basePackages = {"com.gitee.dbapi.data.dao.mysql"}, sqlSessionTemplateRef = "mysqlSessionTemplate") public class MysqlDatasourceConfig extends DatasourceConfig { protected static String[] MYBATIS_MAPPER_LOCATIONS = new String[]{"classpath*:/mapper/mysql/*.xml"}; protected static String MYBATIS_BASE_PACKAGE = "com.gitee.dbapi.data.dao.mysql"; @Autowired JavaConfig javaConfig; @Qualifier("mysqlDataSource") @Bean("mysqlDataSource") //@ConfigurationProperties("spring.datasource.mysql") @Primary public DataSource mysqlDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setRemoveAbandoned(true); dataSource.setRemoveAbandonedTimeout(1800); // 30分钟 dataSource.setLogAbandoned(true); DbConfigDto mysql = javaConfig.FindMysql(); dataSource.setUsername(javaConfig.FindMysql().getUsername()); dataSource.setPassword(javaConfig.FindMysql().getPassword()); dataSource.setUrl(javaConfig.FindMysql().getUrl()); dataSource.setDriverClassName(javaConfig.FindMysql().getDriverClassName()); dataSource.setMaxWait(javaConfig.FindMysql().getMaxWait()); dataSource.setInitialSize(mysql.getInitialSize()); dataSource.setTestOnBorrow(false); dataSource.setValidationQuery(mysql.getValidationQuery()); return dataSource; }
}
APP
@SpringBootApplication(scanBasePackages = {"com.gitee"},exclude={DruidDataSourceAutoConfigure.class, DataSourceAutoConfiguration.class}) @EnableEurekaClient @EnableFeignClients(basePackages = "com.gitee.dbapi") @EnableSwagger2 @EnableApolloConfig @EnableDiscoveryClient public class Dbapi { public static void main(String[] args) { try { SpringApplication.run(Dbapi.class, args); } catch (Exception e) { e.printStackTrace(); } } }
java config
@Component @Data @ConfigurationProperties(prefix = "spring") public class JavaConfig implements Serializable { private static final long serialVersionUID = 1L; @Autowired Map<String ,DbConfigDto> datasource; @PostConstruct public void decrypt() { FindMysql().setPassword(DbEncryptUtil.decrypt(FindMysql().getPassword())); }
public String Encrypt(String in) { return DbEncryptUtil.encrypt(in); }
public DbConfigDto FindMysql(){ return datasource.get("mysql"); }
@PostConstruct public void logInfo() { log.info("========== 应用配置 =========="); log.info("javaConfig info:{}",this); log.info("============================="); }
}
String r = DbEncryptUtil.encrypt("xxxxx@16xx3.comL");
@Data @Component public class DbConfigDto { boolean enabled; boolean testWhileIdle;//: true String driverClassName;//: oracle.jdbc.driver.OracleDriver String url;//: jdbc:oracle:thin:@192.168.4.111:1521:XE String username;//: leijmdas String password;//: leijmdas int maxWait;//: 15000 int initialSize;//: 5 int minIdle;//: 2 boolean testOnBorrow;//: false String validationQuery;//: SELECT 1 }
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-extension</artifactId> <version>3.4.1</version> </dependency>
package com.gitee.base.utils; import org.apache.commons.lang.StringUtils; import com.baomidou.mybatisplus.core.toolkit.AES; public class DbEncryptUtil { private static final String SECRET_KEY = "kunlong976823123"; public static String encrypt(String data) { return AES.encrypt(data, SECRET_KEY); } public static String decrypt(String data) { if (IfEncypt(data)){ data= StringUtils.remove(data,"enc("); data= StringUtils.remove(data,")"); return AES.decrypt(data, SECRET_KEY); } return data; } public static boolean IfEncypt (String data) { return data.startsWith("enc("); } }
Hutool提供了简洁强大的AES加密解密支持,以下是关键实现方法和注意事项:
🔑 一、基础加解密实现
-
添加依赖(Maven)
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.20</version> </dependency>
-
ECB模式加解密(默认模式,无需IV)
// 加密(16进制结果) String encrypted = SecureUtil.aes(key.getBytes()).encryptHex(content); // 解密 String decrypted = SecureUtil.aes(key.getBytes()).decryptStr(encrypted);
注:密钥需为 16/24/32字节(如
1234567890123456
)。 -
Base64输出格式
// 加密(Base64) String encryptBase64 = SecureUtil.aes(key.getBytes()).encryptBase64(content); // 解密 String decryptStr = SecureUtil.aes(key.getBytes()).decryptStr(encryptBase64);
⚙️ 二、高级配置(CBC模式)
需指定初始化向量(IV)和填充方式:
// 密钥(16字节)和IV(16字节)
String key = "xxx", iv = "sdfsdf12345sfsdf";
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes(), "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv.getBytes());
// 创建CBC模式AES对象
AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, keySpec, ivSpec);
// 加密
String encrypted = aes.encryptHex(content);
// 解密
String decrypted = aes.decryptStr(encrypted);
ECB vs CBC模式对比
特性 | ECB模式 | CBC模式 |
---|---|---|
初始化向量 | 不需要 | 必须16字节 |
安全性 | 较低(相同明文输出相同密文) | 更高(引入随机性) |
适用场景 | 简单加密需求 | 敏感数据加密 |
⚠️ 三、关键注意事项
-
密钥管理
-
禁止硬编码:密钥应存储于安全配置中心(如Vault)。
-
长度校验:AES密钥需严格为16/24/32字节,否则报错
Key length not 128/192/256 bits
。
-
-
编码一致性
加解密时需统一字符编码(推荐UTF-8):
String decrypted = aes.decryptStr(encrypted, CharsetUtil.CHARSET_UTF_8);
-
异常处理
捕获
CryptoException
,避免密钥错误导致服务中断:try { String decrypted = aes.decryptStr(encrypted); } catch (CryptoException e) { log.error("解密失败: {}", e.getMessage()); }
🔧 四、实用技巧
-
URL参数加密
加密后拼接URL:
String param = "userId=114&tenantId=2"; String encryptedParam = SecureUtil.aes(key.getBytes()).encryptHex(param); String url = "/api?data=" + URLEncoder.encode(encryptedParam);
-
密钥动态生成(仅测试环境)
byte[] randomKey = SecureUtil.generateKey(SymmetricAlgorithm.AES.getValue()).getEncoded();
💎 五、最佳实践建议
-
算法选择:优先使用AES而非DES(DES已证实不安全)。
-
模式推荐:敏感数据采用CBC+PKCS7填充或更安全的GCM模式。
-
密钥轮转:定期更新密钥并兼容历史数据解密。
通过Hutool,仅需1-2行代码即可实现企业级AES加密,兼顾安全性与开发效率。建议结合具体业务需求选择模式,并严格遵循密钥安全管理规范。