ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

关于为什么jdbc配置中不能使用${username}问题,jdbc中username不生效问题,system-properties-mode取值----Spring配置jdbc的坑

2022-01-05 13:10:56  阅读:109  来源: 互联网

标签:username jdbc Spring system mysql com properties


文章目录

今天遇到一个坑,刚爬出来,填上以惠及他人


问题:

spring配置jdbc时,dataConfig.properties里的username不生效,jdbc配置中不能使用${username}问题



情景:

我databaseConfig.properties里的配置是这样子的

url=jdbc:mysql://localhost:3306/springstudy?characterEncoding=utf-8&serverTimezone=UTC
driverClassname=com.mysql.jdbc.Driver
username=root
password=root

下面是我xml里面的配置

    <context:property-placeholder location="databaseConfig.properties"/>
    
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
        <property name="url" value="${url}"/>
        <property name="driverClassName" value="${driverClassname}"/>
    </bean>
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource"/>
    </bean>

下面是建立连接是报的错,注意第二行当中的“Access denied for user ‘Tptogiar’@‘localhost’ (using password: YES)”,其中Tptogiar是我电脑的用户名。但是我properties里面配置的是root呀,为什么最终出来的dataSource对象里面的用户名确实我电脑的用户名?

严重: create connection SQLException, url: jdbc:mysql://localhost:3306/springstudy?characterEncoding=utf-8&serverTimezone=UTC, errorCode 1045, state 28000
java.sql.SQLException: Access denied for user 'Tptogiar'@'localhost' (using password: YES)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
	at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:833)
	at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:453)
	at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:246)
	at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:198)
	at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1644)
	at com.alibaba.druid.pool.DruidAbstractDataSource.createPhysicalConnection(DruidAbstractDataSource.java:1710)
	at com.alibaba.druid.pool.DruidDataSource$CreateConnectionThread.run(DruidDataSource.java:2774)

为了确定我的数据库能不能连上,我写了个测试类

public class TestDruid {
    @Test
    public void testDruid() throws SQLException {
        BasicDataSource source = new  BasicDataSource();
        source.setDriverClassName( "com.mysql.jdbc.Driver" );
        source.setUrl( "jdbc:mysql:///springstudy" );
        source.setUsername( "root" );
        source.setPassword( "root" );
        Connection conn = source.getConnection();
        System.out.println(conn);
        System.out.println(conn.isClosed());
    }
}

结果输出也是正常的



发现原因:

原来在上面xml里面的配置context:property-placeholder时,如果没有指定属性system-properties-mode的值时,会默认设置为“ENVIRONMENT”。这个取值会有什么影响呢?
跟进去源码spring-context.xsd里面查看关于标签的定义。在定义里面可以发现官方对于这个property-placeholder标签里的system-properties-mode属性取值的相关说明(英文注释部分)。

	<xsd:element name="property-placeholder">
		<xsd:annotation>
			<xsd:documentation><![CDATA[
	Activates replacement of ${...} placeholders by registering a
	PropertySourcesPlaceholderConfigurer within the application context. Properties will
	be resolved against the specified properties file or Properties object -- so called
	"local properties", if any, and against the Spring Environment's current set of
	PropertySources.

	Note that as of Spring 3.1 the system-properties-mode attribute has been removed in
	favor of the more flexible PropertySources mechanism. However, applications may
	continue to use the 3.0 (and older) versions of the spring-context schema in order
	to preserve system-properties-mode behavior. In this case, the traditional
	PropertyPlaceholderConfigurer component will be registered instead of the newer
	PropertySourcesPlaceholderConfigurer.

	See ConfigurableEnvironment javadoc for more information on usage.
			]]></xsd:documentation>
			<xsd:appinfo>
				<tool:annotation>
					<tool:exports type="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"/>
				</tool:annotation>
			</xsd:appinfo>
		</xsd:annotation>
		<xsd:complexType>
			<xsd:complexContent>
				<xsd:extension base="propertyLoading">
					<xsd:attribute name="system-properties-mode" default="ENVIRONMENT">
						<xsd:annotation>
							<xsd:documentation><![CDATA[
	Controls how to resolve placeholders against system properties. As of Spring 3.1, this
	attribute value defaults to "ENVIRONMENT", indicating that resolution of placeholders
	against system properties is handled via PropertySourcesPlaceholderConfigurer and its
	delegation to the current Spring Environment object.

	For maximum backward compatibility, this attribute is preserved going forward with the
	3.1 version of the context schema, and any values other than the default "ENVIRONMENT"
	will cause a traditional PropertyPlaceholderConfigurer to be registered instead of the
	newer PropertySourcesPlaceholderConfigurer variant. In this case, the Spring Environment
	and its property sources are not interrogated when resolving placeholders. Users are
	encouraged to consider this attribute deprecated, and to take advantage of the
	Environment and PropertySource mechanisms. See ConfigurableEnvironment javadoc for examples.

	"ENVIRONMENT" indicates placeholders should be resolved against the current Environment and against any local properties;
	"NEVER" indicates placeholders should be resolved only against local properties and never against system properties;
	"FALLBACK" indicates placeholders should be resolved against any local properties and then against system properties;
	"OVERRIDE" indicates placeholders should be resolved first against system properties and then against any local properties;
							]]></xsd:documentation>
						</xsd:annotation>
						<xsd:simpleType>
							<xsd:restriction base="xsd:string">
								<xsd:enumeration value="ENVIRONMENT"/>
								<xsd:enumeration value="NEVER"/>
								<xsd:enumeration value="FALLBACK"/>
								<xsd:enumeration value="OVERRIDE"/>
							</xsd:restriction>
						</xsd:simpleType>
					</xsd:attribute>
					<xsd:attribute name="value-separator" default=":">
						<xsd:annotation>
							<xsd:documentation><![CDATA[
	The separating character between the placeholder variable and the associated
	default value: by default, a ':' symbol.
				]]></xsd:documentation>
						</xsd:annotation>
					</xsd:attribute>
					<xsd:attribute name="trim-values">
						<xsd:annotation>
							<xsd:documentation><![CDATA[
	Whether to trim resolved values before applying them, removing superfluous
	whitespace (in particular tab characters) from the beginning and end.
				]]></xsd:documentation>
						</xsd:annotation>
					</xsd:attribute>
					<xsd:attribute name="null-value">
						<xsd:annotation>
							<xsd:documentation><![CDATA[
	A value that should be treated as 'null' when resolved as a placeholder value:
	e.g. "" (empty String) or "null". By default, no such null value is defined.
				]]></xsd:documentation>
						</xsd:annotation>
					</xsd:attribute>
				</xsd:extension>
			</xsd:complexContent>
		</xsd:complexType>
	</xsd:element>

大概的翻译一下上面源码在讲什么:

首先最外层标签xsd:element定义了一个context命名空间下(这里是在spring-context.xsd文件下)的一个property-placeholder标签,然后又定义了关于这个标签的一下其他东西。然后重点来了,在这个标签属性定义那里xsd:attribute定义了一个名为system-properties-mode的属性,然后默认值设置为ENVIRONMENT,即源码中的这部分

<xsd:attribute name="system-properties-mode" default="ENVIRONMENT">

然后我们再看一下官方关于这个属性的取值的说明,发现他说:

	"ENVIRONMENT" indicates placeholders should be resolved against the current Environment and against any local properties;
	"NEVER" indicates placeholders should be resolved only against local properties and never against system properties;
	"FALLBACK" indicates placeholders should be resolved against any local properties and then against system properties;
	"OVERRIDE" indicates placeholders should be resolved first against system properties and then against any local properties;
system-properties-mode的值取:
ENVIRONMENT
   在XML文件里面用${ }获取值的时候,会优先从本地计算机环境里面获取(这也叫说明了,为什么上文我jdbc里面username一直变为我的电脑的用户名),然后再从我们指定的properties文件里面获取
NEVER
   在XML文件里面用${ }获取值的时候,仅仅会从我们指定的properties文件里面获取
FALLBACK
   表示如果给定的配置文件properties没有该属性的话检查系统配置文件
OVERRIDE
   表示在检查特定的配置文件properties之前先检查系统配置文件






解决问题

关于jdbc配置中不能使用${username}问题,dataConfig.properties里的username不生效

通过上面我们知道当system-properties-mode去ENVIRONMENT时,解析${ }时是先回去环境里面找的,而环境里面刚好有一个key为username的值的话就会被覆盖,我们自己配置的值就会失效,所以为了避免被覆盖,换个名称就可以了

或者我们也可以直接修改system-properties-mode的取值为NEVER来避免覆盖

在这里插入图片描述

标签:username,jdbc,Spring,system,mysql,com,properties
来源: https://blog.csdn.net/weixin_54430656/article/details/122320606

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有