По сути, у вас есть готовый JAR-файл, который вы хотите перенести в другую среду, и без каких-либо изменений он должен подобрать соответствующие свойства во время выполнения. Если это правильно, то следующие подходы действительны:
1) Положитесь на наличие файла свойств в домашнем каталоге пользователя.
Настройте PropertyPlaceholderConfigurer для ссылки на файл свойств, внешний по отношению к JAR, следующим образом:
<bean id="applicationProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="false"/>
<property name="order" value="1"/>
<property name="locations">
<list>
<!-- User home holds secured information -->
<value>file:${user.home}/MyApp/application.properties</value>
</list>
</property>
</bean>
Операционная система будет защищать содержимое файла application.properties, чтобы к нему могли иметь доступ только нужные люди. Поскольку этот файл не существует при первом запуске приложения, при запуске создайте простой скрипт, который будет запрашивать у пользователя критические значения (например, имя пользователя, пароль, диалект Hibernate и т. Д.). Предоставьте обширную справку и разумные значения по умолчанию для интерфейса командной строки.
2) Если ваше приложение находится в контролируемой среде, чтобы можно было увидеть базу данных, проблема может быть сведена к одному из создания базовых учетных данных с использованием метода 1), описанного выше, для подключения к базе данных во время запуска контекста и последующей замены используя значения, прочитанные через JDBC. Вам потребуется двухэтапный подход к запуску приложения: фаза 1 вызывает родительский контекст с файлом application.properties, заполняющим JdbcTemplate и связанный DataSource; Фаза 2 вызывает основной контекст, который ссылается на родительский элемент, так что JdbcTemplate может использоваться, как настроено в JdbcPropertyPlaceholderConfigurer.
Пример кода такого типа:
public class JdbcPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
private Logger log = Logger.getLogger(JdbcPropertyPlaceholderConfigurer.class);
private JdbcTemplate jdbcTemplate;
private String nameColumn;
private String valueColumn;
private String propertiesTable;
/**
* Provide a different prefix
*/
public JdbcPropertyPlaceholderConfigurer() {
super();
setPlaceholderPrefix("#{");
}
@Override
protected void loadProperties(final Properties props) throws IOException {
if (null == props) {
throw new IOException("No properties passed by Spring framework - cannot proceed");
}
String sql = String.format("select %s, %s from %s", nameColumn, valueColumn, propertiesTable);
log.info("Reading configuration properties from database");
try {
jdbcTemplate.query(sql, new RowCallbackHandler() {
public void processRow(ResultSet rs) throws SQLException {
String name = rs.getString(nameColumn);
String value = rs.getString(valueColumn);
if (null == name || null == value) {
throw new SQLException("Configuration database contains empty data. Name='" + name + "' Value='" + value + "'");
}
props.setProperty(name, value);
}
});
} catch (Exception e) {
log.fatal("There is an error in either 'application.properties' or the configuration database.");
throw new IOException(e);
}
if (props.size() == 0) {
log.fatal("The configuration database could not be reached or does not contain any properties in '" + propertiesTable + "'");
}
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public void setNameColumn(String nameColumn) {
this.nameColumn = nameColumn;
}
public void setValueColumn(String valueColumn) {
this.valueColumn = valueColumn;
}
public void setPropertiesTable(String propertiesTable) {
this.propertiesTable = propertiesTable;
}
}
Вышеприведенное будет затем сконфигурировано в Spring следующим образом (обратите внимание, что свойство order следует после обычных заполнителей с префиксом $):
<!-- Enable configuration through the JDBC configuration with fall-through to framework.properties -->
<bean id="jdbcProperties" class="org.example.JdbcPropertyPlaceholderConfigurer">
<property name="ignoreUnresolvablePlaceholders" value="false"/>
<property name="order" value="2"/>
<property name="nameColumn" value="name"/>
<property name="valueColumn" value="value"/>
<property name="propertiesTable" value="my_properties_table"/>
<property name="jdbcTemplate" ref="configurationJdbcTemplate"/> <!-- Supplied in a parent context -->
</bean>
Это позволит выполнить следующее в конфигурации Spring
<!-- Read from application.properties -->
<property name="username">${username}</property>
...
<!-- Read in from JDBC as part of second pass after all $'s have been fulfilled -->
<property name="central-thing">#{name.key.in.db}</property>
3) Конечно, если вы находитесь в контейнере веб-приложения, вы просто используете JNDI. Но ты не такой, ты не можешь.
Надеюсь, это поможет!