Можно ли использовать classpath для переопределения файла в запущенной банке?
У меня есть JAR файл, содержащий приложение, а также файлы конфигурации для этого приложения. Приложение загружает файлы конфигурации из пути к классам (используя ClassLoader.getResource()
) и полностью удовлетворяет его зависимостям, используя файлы конфигурации, запеченные в JAR файле.
Иногда я хочу, чтобы приложение запускалось с немного другой конфигурацией (в частности, я хочу переопределить URL JDBC, чтобы указать на другую базу данных), поэтому я создаю новый файл конфигурации, сохраняю его в правильной структуре каталогов (который означает в каталоге /config
элемента classpath), и я хочу сделать что-то вроде этого:
java -cp new-config:. -jar application.jar
Но я не могу заставить classpath иметь запись пути new-config
до содержимого JAR приложения. Является ли жестко закодированным, что содержимое JAR всегда является первым в пути к классам?
Ответы
Ответ 1
Почему бы просто не вызвать приложение без указания -jar и вместо этого назвать основной класс приложения явно? Это позволит вам поместить как ваш новый-config, так и application.jar в путь класса в требуемом порядке:
например. (предполагая, что "new-config" - это каталог, содержащий файл переопределенных свойств)
java -cp new-config:application.jar Application.Main.Class
Я считаю, что имя основного класса можно найти в файле MANIFEST.MF внутри jar....
Ответ 2
Когда вы используете параметр -jar для запуска приложения:
... JAR файл является источником всех классы пользователей и другой пользовательский класс параметры пути игнорируются.
как описано здесь. Обходным путем было бы указать путь класса в манифесте файла jar, чтобы включить дополнительный путь (описанный здесь).
Однако, учитывая, что вы говорите только о внесении изменений в конфигурацию, вы можете использовать другой подход, который не зависит от пути к классам. Например, я обычно настраиваю свои приложения через Spring с помощью файлов свойств для определения местоположения баз данных и т.д. Моя конфигурация Spring является последовательной в тестовых, QA и живых средах, но я передаю другой файл свойств в качестве аргумента командной строки при запуске приложения.
Spring Фрагмент конфигурации
<bean id="MyDataSource" class="org.springframework.jdbc.datasource.SingleConnectionDataSource">
<property name="url" value="jdbc:microsoft:sqlserver://${dbServer}:${dbPort};DatabaseName=${dbName}"/>
<property name="username" value="${dbUserName}"/>
<property name="password" value="${dbPassword}"/>
<property name="suppressClose" value="false"/>
</bean>
Файл описания файла
dbServer=MyServer
dbPort=1433
dbName=MyDb
dbUserName=Me
dbPassword=foobar
Ответ 3
Архив JAR, указанный параметром -jar, переопределяет все другие значения.
Вам придется в основном делать это с внешним конфигурационным файлом или создавать собственное решение с ClassLoader.getResource()
.
Мы используем специальное решение для решения этого вопроса: мы загружаем внутренние свойства следующим образом:
final Properties p = new Properties();
p.load(DefaultConfiguration.class.getResourceAsStream("config.properties"));
Затем мы загружаем внешний файл таким же образом и перезаписываем внутренние значения внешними.
Информацию о том, как работает загрузка классов, выглядит следующим образом:
http://java.sun.com/javase/6/docs/technotes/tools/findingclasses.html
Ответ 4
Это может быть невозможно, используя только CLASSPATH. Есть способы заставить вызов ClassLoader.getResource()
использовать статический путь для поиска ресурса. Если он делает это, он обходит CLASSPATH.