1. 程式人生 > >通過Spring讀取properties配置檔案

通過Spring讀取properties配置檔案

一般properties檔案,用於在程式碼塊中讀取,並給變數賦值。但是,Spring可以Bean XML方式定義(註冊Bean)中,可以通過${屬性名}使用properties檔案配置的值。或者在程式碼中使用@Value註解讀取properties的屬性值。
所以用途有兩種:

1. 用途

1.1.  Spinrg的Bean XML定義中,可以通過${屬性名}使用properties檔案配置的值

首先,必須先載入properties配置檔案,方式有兩種,如下

方式一:

<!-- 
	  用途1:Spring的xml配置檔案中,可以通過${屬性名}使用properties檔案配置的值
	  用途2:可以使用@Value("${屬性名}")註解讀取properties檔案配置的值,再給欄位賦值
	         方法1:註解在欄位上,給欄位賦值
	         方法2:註解在欄位的setter方法中賦值           
-->
<context:property-placeholder location="classpath:jdbc.properties"/>

方式二:

<!-- 
	  用途1:Spring的xml配置檔案中,可以通過${屬性名}使用properties檔案配置的值
	  用途2:可以使用@Value("${屬性名}")註解讀取properties檔案配置的值,再給欄位賦值
	         方法1:註解在欄位上,給欄位賦值
	         方法2:註解在欄位的setter方法中賦值           
-->
<bean id="propertyConfigurer"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
      <property name="location">
          <value>/WEB-INF/configs/sqlServer.properties</value>
      </property>
</bean>

可以清楚的看到,方式一,非常地簡潔,但是如果要使用多個properties就可能實現不了,其實可以通過萬用字元實現,會有點麻煩。

接著,就可以在Bean的定義中,使用properties中的屬性值,如下

<bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName">
          <value>${jdbc.driver}</value>
      </property>
      <property name="url" >
          <value>${jdbc.url}</value>
      </property>
      <property name="username" >
          <value>${jdbc.user}</value>
      </property>
      <property name="password">
          <value>${jdbc.pwd}</value>
      </property>
</bean>

1.2.  使用@Value註解讀取properties檔案配置的值,再給欄位賦值

@Value註解是Spring 3.0 之後引入的新特性 

@Value的值有三種類型,#{} 、${} 和 #{'${}'} ,其實是#{}和${}這兩種型別,#{'${}'} 這種是前兩種的巢狀使用,下面分別介紹

1)  #{expression?:default value}

     但是,這種方式下,有個缺陷,那就是 properties配置檔案中的屬性名稱不能帶點,否則取不到值,會報錯

如 file.uploadpath = E:\\360Downloads\\temp , 讀取該屬性值,就會報錯,如下

	@Value("#{prop.file.uploadpath}")
	private String uploadPath;
Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'file' cannot be found on object of type 'java.util.Properties' - maybe not public?

     要使用這種型別的Value值,實現方式有兩種,如下

    方式一:

<!-- 
	    用途:可以使用@Value("#{prop.屬性名}")註解讀取properties檔案配置的值,再給欄位賦值
	         方法1:註解在欄位上,給欄位賦值
	         方法2:註解在欄位的setter方法中賦值
	         注意:@Value("#{prop.屬性名}") 中的 prop 是 註冊的PropertiesFactoryBean的 Bean ID
-->
<bean id="prop" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
 	<property name="locations">
 		<array>
 			<value>classpath:fileupload.properties</value>
 		</array>
 	</property>
</bean>

    方式二:

<!-- 
	    用途:可以使用@Value("#{prop.屬性名}")註解讀取properties檔案配置的值,再給欄位賦值
	         方法1:註解在欄位上,給欄位賦值
	         方法2:註解在欄位的setter方法中賦值
	         注意:@Value("#{prop.屬性名}") 中的 prop 是 註冊的PropertiesFactoryBean的 Bean ID
-->
<util:properties id="prop" location="classpath:fileupload.properties"/>

       可以清楚的看到,方式二,非常地簡潔,但是如果要使用多個properties就可能實現不了,其實可以通過萬用字元實現,會有點麻煩。

接下來,看demo

fileupload.properties檔案:

name=zengyanhui
age=12

Test.java:

package edu.mvcdemo.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @編寫人: yh.zeng
 * @編寫時間:2017-7-26 下午11:04:10
 * @檔案描述: todo
 */
@Component("test")
@Scope("singleton")
public class Test {
	@Value("#{prop.name}")
	private String name;
	
	@Value("#{prop.age}")
	private String age;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}
	
}

SpringBeanUtilsTest.java:

package edu.mvcdemo.utils;

import edu.mvcdemo.service.Test;
import junit.framework.TestCase;

/**
 * @編寫人: yh.zeng
 * @編寫時間:2017-7-26 下午11:09:38
 * @檔案描述: todo
 */
public class SpringBeanUtilsTest  extends TestCase{

	public void test1(){
		SpringBeanUtils.setFilePath("src/springCfg/applicationContext-base.xml");
		Test test = (Test) SpringBeanUtils.getBean("test");
		System.out.println("name="+test.getName());
		System.out.println("age="+test.getAge());
	}
	
}

程式執行結果:

[INFO][2017-07-27 23:50:59][AbstractApplicationContext:583] - Refreshing org.[email protected]b8d805: startup date [Thu Jul 27 23:50:59 CST 2017]; root of context hierarchy
[INFO][2017-07-27 23:50:59][XmlBeanDefinitionReader:317] - Loading XML bean definitions from file [D:\EclipseWorkspace\MavenSpringMvcDemo\src\springCfg\applicationContext-base.xml]
name=zengyanhui
age=12

2)${property:default value}

    ${}這種值,只用來讀取properties配置檔案中的屬性值, :  前面的是屬性名稱,:  後面的是預設值。這種型別的值,卻可以讀取帶點的屬性值,如 file.uploadpath = E:\\360Downloads\\temp,可以使用@Value("${file.uploadpath}")讀取

     要使用這種方式的Value,有兩種實現方式,如下

     方式一:

<!-- 
	    用途1:Spring的xml配置檔案中,可以通過${屬性名}使用properties檔案配置的值
	    用途2:可以使用@Value("${屬性名}")註解讀取properties檔案配置的值,再給欄位賦值
	           方法1:註解在欄位上,給欄位賦值
	           方法2:註解在欄位的setter方法中賦值           
-->
<bean id="propertyConfigurer"  
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
      <property name="location">  
          <value>classpath:fileupload.properties</value>  
      </property>  
</bean>  

      方式二:

<!-- 
	    用途1:Spring的xml配置檔案中,可以通過${屬性名}使用properties檔案配置的值
	    用途2:可以使用@Value("${屬性名}")註解讀取properties檔案配置的值,再給欄位賦值
	           方法1:註解在欄位上,給欄位賦值
	           方法2:註解在欄位的setter方法中賦值           
-->
<context:property-placeholder  location="classpath:fileupload.properties"/>

可以清楚的看到,方式二,非常地簡潔,但是如果要使用多個properties就可能實現不了,其實可以通過萬用字元實現,會有點麻煩。

下面看demo:

package edu.mvcdemo.service;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

/**
 * @編寫人: yh.zeng
 * @編寫時間:2017-7-26 下午11:04:10
 * @檔案描述: todo
 */
@Component("test")
@Scope("singleton")
public class Test {
	@Value("${name}")
	private String name;
	
	@Value("${age}")
	private String age;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

}

程式執行結果:

[INFO][2017-07-27 23:50:59][AbstractApplicationContext:583] - Refreshing org.[email protected]b8d805: startup date [Thu Jul 27 23:50:59 CST 2017]; root of context hierarchy
[INFO][2017-07-27 23:50:59][XmlBeanDefinitionReader:317] - Loading XML bean definitions from file [D:\EclipseWorkspace\MavenSpringMvcDemo\src\springCfg\applicationContext-base.xml]
name=zengyanhui
age=12

 (3)#{'${}'}

    這種型別的Value值,是#{}裡面巢狀${}使用,所以必須按照上述的(1)(2)兩種型別的實現方式,配置properties檔案,才可以使用這種方式的值

	@Value("#{'${age}'}")
	private String age;

參考資料: