遇到的问题:程序运行时,连接数据库报错,如下图
错误信息意思是访问被拒,先追踪报错信息到DruidDataSource.java这个类的init()这个方法的870行,如下图
也就是说,在这个try的方法块里抛出了异常,开始从859行断点,进入createPhysicalConnection()方法,
调到这里,瞬间就明白了,密码是未解密的密文,当然连不上数据库了。顺着往下调,刚好找到了解决问题的办法
Druid可以配置一个叫做passwordCallBack的参数,这个参数的值是一个全限定类名,这个类需要继承DruidPasswordCallback.java类,实现一个setProperties()方法,在这个方法里,可以将加密的密码通过Druid提供的ConfigTools.decrypt(publickey, password)方法进行解密,再通过DruidPasswordCallback.java类的父类PasswordCallback.java的setPassword()的方法赋值解密后的密码,再看上面图中1545行代码,password获得的值就是解密后的密码,请求连接数据库就没问题了。
整个问题处理的思路整理完了,下面把关键代码奉上。
import com.alibaba.druid.filter.config.ConfigTools; import com.alibaba.druid.util.DruidPasswordCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Properties; public class DbPasswordCallback extends DruidPasswordCallback { private static final Logger LOGGER = LoggerFactory.getLogger(DbPasswordCallback.class); @Override public void setProperties(Properties properties) { super.setProperties(properties); String password = (String) properties.get("password"); String publickey = (String) properties.get("publickey"); try { String dbpassword = ConfigTools.decrypt(publickey, password); setPassword(dbpassword.toCharArray()); } catch (Exception e) { LOGGER.error("Druid ConfigTools.decrypt", e); } } }
这个是密码回调类,主要处理解密逻辑。
import com.alibaba.druid.pool.DruidDataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; import java.sql.SQLException; @Configuration @MapperScan(basePackages = DbConfig.PACKAGE, sqlSessionFactoryRef = "sqlSessionFactory") public class DbConfig { private static final Logger LOGGER = LoggerFactory.getLogger(DbConfig.class); static final String PACKAGE = "com.xxx.xx.dao"; private static final String MAPPER_LOCATION = "classpath*:mapper/*.xml"; private static final String DOMAIN_PACKAGE = "com.xxx.xx.dao.pojo"; @Value("${spring.datasource.druid.url}") private String dbUrl; @Value("${spring.datasource.druid.username}") private String username; @Value("${spring.datasource.druid.password}") private String password; @Value("${spring.datasource.druid.driver-class-name}") private String driverClassName; @Value("${spring.datasource.type}") private String dbType; @Value("${spring.datasource.druid.initial-size}") private int initialSize; @Value("${spring.datasource.druid.min-idle}") private int minIdle; @Value("${spring.datasource.druid.max-active}") private int maxActive; @Value("${spring.datasource.druid.max-wait}") private int maxWait; @Value("${spring.datasource.druid.time-between-eviction-runs-millis}") private int timeBetweenEvictionRunsMillis; @Value("${spring.datasource.druid.min-evictable-idle-time-millis}") private int minEvictableIdleTimeMillis; @Value("${spring.datasource.druid.validation-query}") private String validationQuery; @Value("${spring.datasource.druid.test-while-idle}") private boolean testWhileIdle; @Value("${spring.datasource.druid.test-on-borrow}") private boolean testOnBorrow; @Value("${spring.datasource.druid.test-on-return}") private boolean testOnReturn; @Value("${spring.datasource.druid.pool-prepared-statements}") private boolean poolPreparedStatements; @Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}") private int maxPoolPreparedStatementPerConnectionSize; @Value("${spring.datasource.druid.filters}") private String filters; @Value("${spring.datasource.druid.connection-properties}") private String connectionProperties; @Value("${spring.datasource.druid.password-callback}") private String passwordCallbackClassName; @Bean(name = "dataSource") @Primary public DataSource dataSource() { DruidDataSource datasource = new DruidDataSource(); datasource.setUrl(dbUrl); datasource.setUsername(username); datasource.setPassword(password); datasource.setDriverClassName(driverClassName); datasource.setInitialSize(initialSize); datasource.setMinIdle(minIdle); datasource.setMaxActive(maxActive); datasource.setMaxWait(maxWait); datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); datasource.setValidationQuery(validationQuery); datasource.setTestWhileIdle(testWhileIdle); datasource.setTestOnBorrow(testOnBorrow); datasource.setTestOnReturn(testOnReturn); datasource.setPoolPreparedStatements(poolPreparedStatements); datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize); datasource.setConnectionProperties(connectionProperties); datasource.setDbType(dbType); try { datasource.setPasswordCallbackClassName(passwordCallbackClassName); } catch (Exception e) { LOGGER.error("druid configuration initialization passwordCallbackClassName", e); } try { datasource.setFilters(filters); } catch (SQLException e) { LOGGER.error("druid configuration initialization filter", e); } return datasource; } @Bean(name = "transactionManager") @Primary public DataSourceTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } @Bean(name = "sqlSessionFactory") @Primary public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception { final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dataSource); sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver() .getResources(DbConfig.MAPPER_LOCATION)); sessionFactory.setTypeAliasesPackage(DOMAIN_PACKAGE); sessionFactory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true); return sessionFactory.getObject(); } }
这个是springboot配置Druid时需要显式注入一下数据源配置。
spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url= spring.datasource.username= spring.datasource.password= spring.datasource.druid.url= spring.datasource.druid.username= spring.datasource.druid.password= spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver spring.datasource.druid.initial-size=1 spring.datasource.druid.max-active=20 spring.datasource.druid.min-idle=1 spring.datasource.druid.max-wait=60000 spring.datasource.druid.pool-prepared-statements=false spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20 spring.datasource.druid.validation-query=SELECT 'x' spring.datasource.druid.test-on-borrow=false spring.datasource.druid.test-on-return=false spring.datasource.druid.test-while-idle=true spring.datasource.druid.time-between-eviction-runs-millis=60000 spring.datasource.druid.min-evictable-idle-time-millis=300000 spring.datasource.druid.filters=stat spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.druid.password-callback=com.xxx.xx.dao.util.DbPasswordCallback spring.datasource.publicKey= spring.datasource.druid.connection-properties=config.decrypt=true;publickey=${spring.datasource.publicKey};password=${spring.datasource.druid.password}
这个是springboot的application.properties配置文件。
原文地址:https://blog.csdn.net/ooobama/article/details/80752223
版权声明:本文为CSDN博主「WaOoo....」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ooobama/article/details/80752223