今天遇到了一个很奇怪的问题,在将druid整合进spring的配置文件时,连接数据库出现了

2020-09-18 01:43:42,726 2199 [eate-1151700737] ERROR aba.druid.pool.DruidDataSource - create connection SQLException, url: jdbc:mysql://localhost:3306/ssm_test?useUnicode=true&characterEncoding=utf-8, errorCode 1045, state 28000
java.sql.SQLException: Access denied for user 'root1'@'localhost' (using password: NO)

这明显就是用户连接错误,要么用户名有问题要么密码有问题,然鹅我在druid.properties里配置的username属性值是root啊!

konley是我电脑的用户名,我用idea搜索了整个项目,并没有出现这个字符串。

下面是代码:


1.spring配置文件applicationContext.xml

<context:property-placeholder location="classpath:druid.properties" ignore-unresolvable="true"/>
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
    <property name="driverClassName" value="${driverClassName}"/>
    <property name="url" value="${url}"/>
    <property name="username" value="${username}"/>
    <property name="password" value="${password}"/>
</bean>

2.数据库配置文件 druid.properties

#mysql驱动
driverClassName=com.mysql.jdbc.Driver
#连接地址
url=jdbc:mysql://localhost:3306/ssm_test?useUnicode=true&characterEncoding=utf-8
#用户名
username=root
#密码
password=123456
filters=stat
#  最大并发连接数
maxActive=20
#初始化连接数量
initialSize=1
#超时等待时间以毫秒为单位
maxWait=60000
#最小空闲连接
minIdle=1
#校验连接池中限制时间超过minEvictableIdleTimeMillis的连接对象
timeBetweenEvictionRunsMillis=3000
#连接在池中保持空闲而不被空闲连接回收器线程(如果有)回收的最小时间值,单位毫秒
minEvictableIdleTimeMillis=300000
#SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前
validationQuery=SELECT now();
#指明连接是否被空闲连接回收器(如果有)进行检验.
#如果检测失败,则连接将被从池中去除.
testWhileIdle=true
#指明是否在从池中取出连接前进行检验,如果检验失败,
#则从池中去除连接并尝试取出另一个.
testOnBorrow=false
#指明是否在归还到池中前进行检验
testOnReturn=false
#poolPreparedStatements=true
maxPoolPreparedStatementPerConnectionSize=20

在网上搜了好久也没发现问题,联想到konley是我的电脑用户名之后,我怀疑可能是导入的时候出现的bug

重新调整搜索策略,还真发现了问题所在:

<context:property-placeholder> 标签的配置问题

如上代码,我使用了

<context:property-placeholder location="classpath:druid.properties" ignore-unresolvable="true"/>

来导入外部的配置文件,而该标签有个 system-properties-mode (系统属性模式)

在不设置的时候**其默认值是 ENVIRONMENT将使用Spring 3.1提供的PropertySourcesPlaceholderConfigurer,其他情况使用Spring 3.1之前的PropertyPlaceholderConfigurer


官方文档如下:

By default it also checks against the Java System properties if it cannot find a property in the specified properties files.

翻译过来就是

默认情况下,如果在指定的属性文件中找不到属性,它还会检查Java系统属性。

好了找到问题了,username属性重名了,spring默认先找系统属性,再找location文件里面的属性

而刚好系统属性里面有一个username就是表示电脑用户名称

也就是直接username=konley(系统用户名)而不去加载我的username=root


解决方法也很简单,

手动设置 <context:property-placeholder> 标签的 system-properties-mode 属性值为 NEVER 或者 FALLBACK

<context:property-placeholder location="classpath:druid.properties" ignore-unresolvable="true" system-properties-mode="NEVER"/>
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
    <property name="driverClassName" value="${driverClassName}"/>
    <property name="url" value="${url}"/>
    <property name="username" value="${username}"/>
    <property name="password" value="${password}"/>
</bean>