- springboot如何獲取配置文件的配置?
- springboot如何在靜態類中獲取配置?
以下所有示例都通過驗證。
1.定義配置文件格式
這裏主要指常見的配置文件:properties, yaml.
當然,json也可以作爲配置,不過不是首選。
使用的配置文件:
application.properties
api.key=jimo
api.password=password
application.yml
api:
username: admin
2.動態注入加載
2.1 @Value
@Component
public class ApiConfig {
@Value("${api.key}")
private String key;
@Value("${api.username}")
private String username;
@Value("${api.password}")
private String password;
}
2.2 @ConfigurationProperties(prefix = “api”)
@Component
@ConfigurationProperties(prefix = "api")
public class ApiConfig {
private String key;
private String username;
private String password;
}
2.3 指定配置文件@PropertySource
@PropertySource
是spring提供的一個註解,用於把特定配置加載到Environment
環境變量裏,標準用法是和Configuration
一起使用。
注意:@PropertySource(value = {"classpath:test.conf"})
對於同一個文件,只需要在一個地方註冊,其他地方都可以使用了。
比如:在主類註冊
@PropertySource(value = {"classpath:test.conf"})
@SpringBootApplication
public class ConfigTestApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigTestApplication.class, args);
}
}
在其他所有bean裏都可以使用:
@Component
public class Api {
@Value("${test.a}")
private String a;
@Value("${test.b}")
private String b;
}
另外:@Value
和@ConfigurationProperties
都是可以和@PropertySource組合使用的,只是注意配置的重複導致覆蓋問題(後加載的會覆蓋前面的).
@Data
@Component
@PropertySource(value = {"classpath:test.conf"})
public class Api4Config {
@Value("${test.a}")
private String a;
@Value("${test.b}")
private String b;
}
3.靜態加載
指在靜態類中讀取配置文件內容
3.1 直接讀取
3.1.1 Properties
我們可以使用最基礎的Properties工具類:這是java的方式
import java.io.IOException;
import java.util.Properties;
import org.springframework.core.io.ClassPathResource;
/**
* 直接讀取配置文件
*
* @author jimo
* @version 1.0.0
*/
public class RawConfigUtil {
private static Properties properties = readProperties("test.conf", "test2.conf");
private static Properties readProperties(String... confFile) {
final Properties properties = new Properties();
try {
for (String path : confFile) {
final ClassPathResource resource = new ClassPathResource(path);
properties.load(resource.getInputStream());
}
} catch (IOException e) {
e.printStackTrace();
}
return properties;
}
public static String getString(String key) {
return properties.getProperty(key);
}
}
3.1.2 typesafe.config
或者通過第三方工具:https://github.com/lightbend/config讀取
<dependency>
<groupId>com.typesafe</groupId>
<artifactId>config</artifactId>
<version>1.4.0</version>
</dependency>
代碼:
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
/**
* @author jimo
* @version 1.0.0
*/
public class ConfigUtils {
private static Config load;
// 默認加載classpath下的application.*
static {
load = ConfigFactory.load();
}
/**
* 讀取配置文件中指定Key的值
*
* @param key 配置文件中的key
* @return 指定key的value
*/
public static String getString(String key) {
return load.getString(key);
}
/**
* 讀取配置文件中指定Key的值
*
* @param key 配置文件中的key
* @return 指定key的value
*/
public static int getInt(String key) {
return load.getInt(key);
}
/**
* 讀取配置文件中指定Key的值
*
* @param key 配置文件中的key
* @return 指定key的value
*/
public static boolean getBoolean(String key) {
return load.getBoolean(key);
}
}
根據其介紹,默認可以加載這些配置文件:
system properties
application.conf (all resources on classpath with this name)
application.json (all resources on classpath with this name)
application.properties (all resources on classpath with this name)
reference.conf (all resources on classpath with this name)
比較特別的是可以讀取json配置,不過筆者用得不多。
3.1.3 小結
但是,這2種方式有以下缺點:
- 都不能讀取yaml格式的配置
- 不能利用springboot從外部和環境變量加載配置的功能,所以只能是死的配置,不夠靈活
3.2 使用Environment
要針對spring環境,還是用spring的工具。
Environment
是在Spring中代表當前運行的環境,包括:profiles
和properties
,
它繼承了PropertyResolver
接口所以才具有讀取配置的功能:
public interface Environment extends PropertyResolver {...}
所以,配置的實現其實是PropertyResolver
接口的實現類做的。
如果我們能在靜態類裏持有這個環境,那麼就可以獲取變量了,恰好spring就提供了這樣的接口:EnvironmentAware
.
public interface EnvironmentAware extends Aware {
/**
* Set the {@code Environment} that this component runs in.
*/
void setEnvironment(Environment environment);
}
這個接口就一個方法:當環境準備好時,會調用這個接口的實現類,然後設置實例。
所以,我們實現這個接口得到Environment:
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
/**
* @author jimo
* @version 1.0.0
*/
@Slf4j
@Component
public class MyEnvBeanUtil implements EnvironmentAware {
private static Environment env;
@Override
public void setEnvironment(Environment environment) {
env = environment;
}
public static String getString(String key) {
return env.getProperty(key);
}
}
我們實際調用時:
@Test
void testEnv() {
assertEquals("password", MyEnvBeanUtil.getString("api.password"));
assertEquals("admin", MyEnvBeanUtil.getString("api.username"));
}
3.3 繼承PropertySourcesPlaceholderConfigurer
PropertySourcesPlaceholderConfigurer
實現了EnvironmentAware
,所以更加豐富,因爲可以設置佔位符這些信息,用於自定義佔位符使用這個,使用方法
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.ConfigurablePropertyResolver;
import org.springframework.core.env.PropertyResolver;
import org.springframework.stereotype.Component;
/**
* @author jimo
* @version 1.0.0
*/
@Component
public class PropertyUtil extends PropertySourcesPlaceholderConfigurer {
private static PropertyResolver propertyResolver;
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess,
ConfigurablePropertyResolver propertyResolver) throws BeansException {
super.processProperties(beanFactoryToProcess, propertyResolver);
PropertyUtil.propertyResolver = propertyResolver;
}
public static String getString(String key) {
return propertyResolver.getProperty(key);
}
}
4.總結
本文對spring獲取配置做了一些總結,主要有以下方式獲取spring的配置:
@Value
@ConfigurationProperties
@PropertySource
指定配置文件Properties
讀取typesafe.config
讀取EnvironmentAware
PropertySourcesPlaceholderConfigurer
後續會總結springboot的多環境配置。