我有一个运行嵌入式Tomcat的SpringBoot应用程序。此侦听器负责从MySQL数据库加载应用程序属性并将其插入到Environment中。它看起来像这样:
@Component
public class DbMigrationAndPropertyLoaderApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
private static final Logger LOGGER = LoggerFactory.getLogger(DbMigrationAndPropertyLoaderApplicationListener.class);
private static final String PROPERTY_SOURCE_NAME = "applicationProperties";
private final int order = Ordered.HIGHEST_PRECEDENCE + 4;
private final PropertySourceProcessor propertySourceProcessor = new PropertySourceProcessor();
@Override
public int getOrder() {
return this.order;
}
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
Properties databaseProperties;
try {
databaseProperties = PropertiesLoaderUtils.loadAllProperties("application-datasource.properties");
} catch (IOException e) {
throw new RuntimeException("Unable to load properties from application-datasource.properties. Please ensure that this file is on your classpath", e);
}
ConfigurableEnvironment environment = event.getEnvironment();
Map<String, Object> propertySource = new HashMap<>();
try {
DataSource ds = DataSourceBuilder
.create()
.username(databaseProperties.getProperty("flyway.user"))
.password(EncryptionUtil.decrypt(databaseProperties.getProperty("flyway.password")))
.url(databaseProperties.getProperty("spring.datasource.url"))
.driverClassName(databaseProperties.getProperty("spring.datasource.driver-class-name"))
.build();
LOGGER.debug("Running Flyway Migrations");
//Run Flyway migrations. If this is the first time, it will create and populate the APPLICATION_PROPERTY table.
Flyway flyway = new Flyway();
flyway.setDataSource(ds);
flyway.migrate();
LOGGER.debug("Initializing properties from APPLICATION_PROPERTY table");
//Fetch all properties
Connection connection = null;
PreparedStatement preparedStatement = null;
ResultSet resultSet = null;
try {
connection = ds.getConnection();
preparedStatement = connection.prepareStatement("SELECT prop_key, prop_value FROM APPLICATION_PROPERTY");
resultSet = preparedStatement.executeQuery();
//Populate all properties into the property source
while (resultSet.next()) {
String propName = resultSet.getString("prop_key");
propertySource.put(propName, propertySourceProcessor.decrypt(resultSet.getString("prop_value")));
}
//Create a custom property source with the highest precedence and add it to the Environment
environment.getPropertySources().addFirst(new MapPropertySource(PROPERTY_SOURCE_NAME, propertySource));
我像这样调用应用程序:
public static void main(String[] args) {
ApplicationContext ctx = new SpringApplicationBuilder(PortalApplication.class)
.listeners(new DbMigrationAndPropertyLoaderApplicationListener())
.build(args)
.run();
我要做的是外化application-datasource.properties文件,使其可以驻留在我的各种应用服务器上(Dev,QA,Prod等)。但是,我无法让侦听器找到此属性文件,我不知道为什么。我尝试将deployment.conf文件中的RUN_ARGS属性设置为
RUN_ARGS = - spring.config.location = /路径/到/ application-datasource.properties
我也尝试将带有属性文件的目录添加到类路径中。我所做的一切似乎都在起作用,但我确信我只是在做一些愚蠢的事情。请注意,加载文件时我没有收到异常,结果属性只是空的。
答案 0 :(得分:1)
Spring Boot使得属性文件加载变得非常容易和轻松。在加载属性和弹簧引导时,你不需要费心。
有许多方法可以使用spring boot加载属性文件,其中一些方法有:
1)只需使用application-{Profile}.properties
在类路径上提供应用程序属性,并将活动的配置文件作为参数--spring.profiles.active= profileName
传递
2)具有spring.config.location
的配置文件,其中已加载的属性被定义为使用的环境属性。 (我们可以从类路径或外部文件路径加载它。
根据spring boot官方文档,默认情况下,配置的位置为classpath:/,classpath:/config/,file:./,file:./config/.
生成的搜索顺序为:
file:./config/
file:./
classpath:/config/
classpath:/
配置自定义配置位置时,除默认位置外,还会使用它们。在默认位置之前搜索自定义位置。例如,如果配置了自定义位置classpath:/custom-config/,file:./custom-config/
,搜索顺序将变为:
file:./custom-config/
classpath:custom-config/
file:./config/
file:./
classpath:/config/
classpath:/
3)您还可以在@PropertySource
类
@Configuration
注释
请参阅this了解更多详情(24.4和24.5)
根据您的评论,您希望在创建任何bean之前加载属性,然后为什么要从类路径中获取它? 通过将其保存在相对文件路径上,可以使其更安全。从相对文件路径读取属性文件时有几个好处。
1)服务器上相对文件路径上的属性文件是安全且无法直接访问的。 2)如果文件被修改,则不需要新的补丁,您只需要重新启动该过程并使用更新的属性。 3)修改所需的努力减少。
以下是符合您要求的示例:
private static Properties loadConfigProps() {
InputStream configStream = null;
Properties _ConfigProps = null;
try {
String prjDir = System.getProperty("user.dir");
String activeProfile = System.getProperty("activeProfile");
int lastIndex = prjDir.lastIndexOf(File.separator);
String configPath = prjDir.substring(0, lastIndex);
configStream = new FileInputStream(new File(configPath
+ File.separator + "_configurations" + File.separator + activeProfile + File.separator
+ "resources" + File.separator + "myDatabaseProperties.properties"));
_ConfigProps = new Properties();
_ConfigProps.load(configStream);
} catch (Exception ex) {
ex.printStackTrace();
System.exit(1);
} finally {
if (null != configStream) {
try {
configStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return _ConfigProps;
}
现在你只需做两件事, 1)创建目录 2)在运行时提供实际的活动配置文件
1)创建目录:
如果您的工作目录是./path/to/applications/active_project
,请在./path/to/applications/
目录中创建新文件夹:
./path/to/applications/
-active_project/
-_configurations/
-QA/myDatabaseProperties.properties
-Dev/myDatabaseProperties.properties
-Prod/myDatabaseProperties.properties
2)在运行时提供实际的活动配置文件:
java -DactiveProfile=Dev -jar jarFileName.jar
答案 1 :(得分:0)
你可以从main方法本身尝试这个。
public static void main(String[] args){
SpringApplication app = new SpringApplication(Application.class);
Map<String, Object> properties = new HashMap<>();
properties.put("spring.profiles.default", "local");
app.setDefaultProperties(properties);
Environment env = app.run(args).getEnvironment();
env.getProperty("spring.application.name")
}
您可以为您设置的环境创建相应的文件。