Подтвердить что ты не робот

Элегантные способы отделить конфигурацию от WAR в Tomcat

Я пытаюсь найти лучший способ передать сложные конфигурации в Spring webapp, запущенном в Tomcat. В настоящее время я использую JNDI для передачи источников данных и строк из контекста Tomcat в webapp, и это хорошо работает.

Но, скажем, мне нужно выбрать реализацию службы уведомлений. Нет никакого способа, чтобы Spring мог условно выбрать, какой bean для создания экземпляра (хотя в прошлом я использовал строку JNDI для импорта предопределенной конфигурации beans путем установки contextConfigLocation).

Я также видел много webapps, которые поставляют инструмент настройки, который создаст пользовательский WAR файл. По-моему, это плохая форма, если только по той причине, что она предотвращает перераспределение WARs вверх по течению без многих проверок, чтобы гарантировать, что вся конфигурация была повторно применена.

В идеале я мог бы предоставить XML файл Spring, который существовал в файловой системе, за пределами webapp. Но директива import Spring, похоже, не разрешает переменные ${}, что делает невозможным предоставление настроек.

Существуют ли какие-либо методы, которые я могу использовать здесь, чтобы правильно отделить сложную конфигурацию от webapp?

4b9b3361

Ответ 1

Если у меня есть определенный набор beans, который я хотел бы настроить, и эта конфигурация должна быть отделена от WAR файла, я обычно делаю следующее:

В applicationContext.xml:

<!-- here you have a configurer based on a *.properties file -->
<bean id="configurer" 
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="file://${configDir}/configuration.properties"/>
    <property name="ignoreResourceNotFound" value="false" />
    <property name="ignoreUnresolvablePlaceholders" value="false" />
    <property name="searchSystemEnvironment" value="false" />
</bean>

<!-- this is how you can use configuration properties -->
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="${smtp.host}"/>
</bean>

В configuration.properties:

smtp.host=smtp.your-isp.com

Вам также нужно запустить Tomcat с помощью -DconfigDir =/path/to/configuration/directory

Ответ 2

Если вы используете Spring 3, вы можете воспользоваться языком выражений Spring. Скажем, у вас есть два приложения app1.war и app2.war, и им нужен файл свойств с именем config.properties. Приложения будут развернуты с помощью контекстных путей /app 1 и/app2.

Создайте два каталога app1 и app2 в общем каталоге, например. C:\myConfig\app1 и C:\myConfig\app2.

Поместите config.properties внутри app1 и еще один config.properties внутри app2.

Затем создайте файл ${CATALINA_HOME}/conf/[enginename]/[hostname]/context.xml.default с содержимым:

context.xml.default:

<Context>
  <Parameter name="myConfigDirectory" value="C:/myConfig" override="false"/>
</Context>

Параметр myConfigDirectory будет доступен для всех приложений на хосте. Лучше создать этот параметр в файле context.xml.default, а не в файле server.xml, потому что файл можно изменить позже, не перезагружая tomcat.

В applicationContext.xml внутри войны вы можете получить доступ к файлам config.properties с помощью выражения SpEL: "# {contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties", так что вы можете написать:

applicationContext.xml:

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
  <property name="location" value="file:#{contextParameters.myConfigDirectory + servletContext.contextPath}/config.properties" />
</bean>

Выражение будет расширено до C:/myConfig/app1 для приложения с contextPath/app1 и C:/myConfig/app2 для приложения с contextPath/app2. Это заставит приложения получить доступ к файлу config.properties на основе их contextPath.

Ответ 3

Если вы хотите полностью переноситься между веб-контейнерами, вы не можете полагаться на что-либо вне своего WAR файла. В Tomcat SecurityManager позволяет вам обнаружить физическое местоположение на диске, где развернут ваш код, и затем вы можете использовать эти знания для перемещения диска в место, где находится ваш файл конфигурации.

См. Определить местоположение класса Java, загруженного Matlab