這篇要來記錄在 Spring MVC 中,
要如何動態地設定 Properties 給 $Value
用的方法。
我們都知道在 spring MVC 中,如果設定了 PropertySourcesPlaceholderConfigurer
,
我們可以把 property file 中的 Key-Value 值讀進來,
之後在 @Component, @Controller, @Service, @Bean 等 Spring 為我們裝配的物件中,
就可以使用 @Value 來取得
property value,例如:
PropertySourcePlaceholderConfigurer 的設定,有兩種方法,使用 xml 或 java config:
- 使用 xml:
- 使用 java config:
mvc-config.xml:
<bean id="propertyConfigurer" class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:xxx1.properties</value> <value>classpath:xxx2.properties</value> </list> </property> <property name="ignoreUnresolvablePlaceholders" value="true" /> </bean>
import java.io.IOException;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;
@Configuration
@PropertySource("classpath:xxx1.properties")
@PropertySource("classpath:xxx2.properties")
public class MyPropertyConfiguration {
@Bean
public static PropertySourcesPlaceholderConfigurer setPropertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(true);
return propertySourcesPlaceholderConfigurer;
}
}
Java 中就可以使用 @Value:
@Component
public class Test
...
@Value("${xxxPropertyKey}")
String xxxPropertyKey;
...
}
但是這樣子因為 property file 的內容本身是寫死的,
如果今天我們想要注入的 @Value 值是專案啟動時動態決定的,
例如從 Database 中讀取而來、從環境變數 (Environment) 中取得、從網路上讀取 (例如 AWS 的 Parameter Store 服務) 等等,
就不能這樣設定了。
我們必須自己實作 PropertySourcesPlaceholderConfigurer 並覆寫掉 (Override) 它的
postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
方法,在裡面實作增添修改 property key-value 值的程式邏輯,
實作的範例如下:
Java:
import java.io.IOException;
import java.util.Properties;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;
@Configuration
@PropertySource("classpath:xxx1.properties")
@PropertySource("classpath:xxx2.properties")
public class MyParameterStorePropertyConfiguration {
//如果原本這邊就有做讀 xxx1.properties 和 xxx2.properties 的 PropertySourcesPlaceholderConfigurer 設定,
//不能因為多做了 setMyParameterStorePropertySourcesPlaceholderConfigurer_2() 就把 setMyParameterStorePropertySourcesPlaceholderConfigurer_1() 拿掉,
//不然 xxx1.properties 和 xxx2.properties 的 property 都會被
//setMyParameterStorePropertySourcesPlaceholderConfigurer_2() 移掉,因為
//setMyParameterStorePropertySourcesPlaceholderConfigurer_2() 中已經用新的 Properties 取代了原本從 xxx1.properties 和 xxx2.properties 讀到的 property
@Bean
public static PropertySourcesPlaceholderConfigurer setMyParameterStorePropertySourcesPlaceholderConfigurer_1() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(true);
//如果不想用 @PropertySource,也可以直接用程式設定,像下面這樣
//propertySourcesPlaceholderConfigurer.setLocations(new ClassPathResource("xx1.properties"), new ClassPathResource("xx2.properties"));
return propertySourcesPlaceholderConfigurer;
}
@Bean
public static PropertySourcesPlaceholderConfigurer setMyParameterStorePropertySourcesPlaceholderConfigurer_2(Environment environment) {
//可視需要看要不要取得環境變數 (Environment)
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer() {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Properties properties = new Properties();
//動態地設定 property,key-value 值可能從其他地方來,而非寫死的 property file,
//例如從 Database 中讀取而來、從環境變數 (Environment) 中取得、從網路上讀取 (例如 AWS 的 Parameter Store 服務) 等等
//do your logic code here to get xxxKey1, xxxValue1, xxxKey2, xxxValue2, ......
properties.put(xxxKey1, xxxValue1);
properties.put(xxxKey2, xxxValue2);
//......
setProperties(properties);
super.postProcessBeanFactory(beanFactory);
}
};
propertySourcesPlaceholderConfigurer.setIgnoreUnresolvablePlaceholders(true);
return propertySourcesPlaceholderConfigurer;
}
}
參考資料:
沒有留言 :
張貼留言