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

Как обеспечить конфигурацию контекста для веб-приложения в Tomcat?

У меня есть веб-приложение, которое полагается на некоторые ресурсы и параметры, которые будут настроены после его установки, например соединение JDBC.

То, что я придумал, это предоставить META-INF/context.xml, который копируется в [engine-name]/[server-name]/[app-name].xml Tomcat при развертывании приложения. Таким образом, все, что я предоставляю, - это файл войны, который можно скопировать в папку appBase (webapps). Документация Tomcat говорит, если есть такой файл, он не будет перезаписан, что действительно здорово, так как изменения, сделанные после развертывания, не будут потеряны.

Но здесь есть тонкий вопрос: Поскольку мы развертываем приложение путем копирования в каталог webapps, Tomcat сначала удалит существующее приложение, а также файл конфигурации. Таким образом, файл конфигурации будет потерян/перезаписан, что нежелательно. Tomcat не изменит это поведение, насколько я знаю.

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

Обратите внимание, что мы не хотим устанавливать autoDeploy в false, и мы не можем использовать человеческое вмешательство для установки (что исключает использование веб-приложения Tomcat Manager).

Если я получаю файл конфигурации из .war файла и копирую его отдельно как [engine-name]/[server-name]/[app-name].xml, Tomcat все равно свяжет его с моим приложением и удалит его после копирования нового .war файла.

Другое предположение: мы заранее не знаем значения конфигурации. Мы предоставим только примерную конфигурацию (если хотите, местозаполнитель), в то время как фактическая конфигурация будет выполнена через некоторое время (не обязательно во время установки).

Спасибо

4b9b3361

Ответ 1

Мне удалось как-то решить эту проблему.

1- Установите взорванный каталог WAR где-нибудь вне Tomcat appBase, допустим, что он находится в /usr/local/MyApp. [Вы можете использовать WAR файл для этого шага вместо каталога WAR, если ваше приложение запускается из невзорванной войны.]

2- Скопируйте файл конфигурации контекста в каталог [tomcat.conf]/[engine]/[hostname], позвоните ему MyApp.xml. Этот файл укажет на местоположение приложения:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Context configuration file for my web application -->
<Context docBase="/usr/local/MyApp" privileged="true" antiResourceLocking="false" antiJARLocking="false">
        <Resource name="jdbc/myapp-ds" auth="Container" type="javax.sql.DataSource"
                maxActive="100" maxIdle="30" maxWait="10000" username="XXX" password="XXX"
                driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/mydb" />
</Context>

3 Теперь вы можете перейти и изменить файл конфигурации.

4- Обновление приложения путем копирования новой версии вашего приложения в /usr/local/MyApp

Примечания:

a) Это решение применимо и к нерасширенному .war файлу, но поскольку мы используем Spring Log4JConfigListener, он не запускается из неразорвавшегося файла .war. Tomcat не взрывает файлы .war, помещенные вне папки appBase (webapps).

b) Этот подход не мешает вам иметь context.xml в /usr/local/MyApp/META -INF/context.xml, поскольку он не будет использоваться Tomcat в этой конфигурации. Вы можете использовать его в своей среде dev, где вы выгружаете свой .war файл в папку appBase (webapps).

Это то, что я получил до сих пор, все еще ищущие лучшие решения.

Ответ 2

Решение прост: не помещайте конфигурацию в свой контекст .xml.

Вот решение, которое мы используем (что хорошо работает для ряда различных внешних клиентов):

У нас есть одна война, которая будет использоваться в нескольких средах, webapp.war. У нас три среды, развитие, интеграция и производство. Интеграция и производство находятся на сайте заказчика. Мы не знаем пароли и пути к файлам для сайтов интеграции и производства клиентов.

Мы используем комбинацию из двух вещей: поиск JNDI для материала базы данных и внешних файлов свойств.

В context.xml, который поставляется на войне, у нас есть ResourceLink

<ResourceLink name="jdbc/webapp"
     global="uk.co.farwell.webapp.datasource.MySqlDataSource" />

Это дает ссылку на глобально определенный источник данных, который определен в server.xml для Tomcat.

<Resource auth="Container" 
          driverClassName="com.mysql.jdbc.Driver" 
          name="uk.co.farwell.webapp.datasource.MySqlDataSource" 
          password="xxx" url="xxx" username="fff" />

Таким образом, данные базы данных можно изменить, отредактировав server.xml без изменения webapp.war. Реально, это нужно делать только один раз для каждого сервера, а не для повторного развертывания.

В нашей конфигурации spring для определения dataSource имеем:

<jee:jndi-lookup id="dataSource" jndi-name="jdbc/webapp" />

Для других свойств у нас есть глобальный файл application.properties, который поставляется вместе с webapp.war, но не является частью войны. На это ссылается -D в командной строке, чтобы запустить Tomcat. -Duk.co.farwell.webapp.applicationDir="/usr/xxx/fff". Мы выбираем определение и читаем файл свойств. Материал базы данных можно было бы сделать так же, но мы потеряли бы объединение, сделанное Tomcat.

Другое дело: нам не нужно перестраивать, если серверы перемещаются, или если по какой-то причине машины меняются. Это вопрос для клиентов и их людей инфраструктуры.

Ответ 3

Обращаясь к Документация Apache Tomcat 5.5:

В файле $CATALINA_HOME/conf/context.xml: элемент контекста информация будет загружена всеми webapps

Вы можете легко попробовать этот подход, он может работать, но я не уверен, что это хорошее решение, особенно если вы используете несколько webapps на Tomcat.

Ответ 4

Вот как мы можем управлять экстернализацией контекста webapp из файла .WAR

  • Поместите ваш .WAR файл где-нибудь за пределами tomcat
  • Создайте файл $APP_NAME.xml в каталоге $TOMCAT_HOME/conf/[Engine]/[Host]/.
  • Теперь файл "$ APP_NAME.xml", который мы только что создали, должен иметь определение контекста и параметры + Any EnvironmentVariable, которые вы хотите использовать для этого контекста.

Например, У меня есть webapp, называемый VirtualWebApp.

Я создам файл, например VirtualWebApp.xml, с определением ниже контекста:

<Context docBase="/home/appBase/VirtualWebApp" path="/VirtualWebApp" reloadable="true">
    <Environment name="webservice.host" type="java.lang.String" value="1.2.3.4" />
    <Environment name="webservice.port" type="java.lang.String" value="4040" />
</Context>

Чтобы получить доступ к этим переменным среды, вы должны написать ниже код (просто искать):

InitialContext initialContext = new javax.naming.InitialContext();

host = (String)initialContext.lookup("java:comp/env/webservice.host");
port = (String)initialContext.lookup("java:comp/env/webservice.port");

Ответ 5

Я не знаю, как изменить поведение Tomcat, но я мог бы подумать о двух разных решениях:

  • разные (параметризованные) скрипты сборки для каждой среды, так что вы определяете параметр с именем env для своих скриптов сборки и в зависимости от значения, которое оно помещает в вашу WAR во время сборки значение context.xml, относящееся к вашей среде.
  • Создайте install script для каждой среды, которая сначала переводит WAR файл (помещает его в каталог webapps), а затем вносит изменения в установку Tomcat в зависимости от среды, например. другое имя хоста для JDBC DataSource в context.xml.

Я использую последний подход, поскольку он работает в корпоративных средах. Политика разделения обязанностей часто запрещает команде разработчиков знать, например. паролей производственной базы данных. Вариант № 2 решает эту проблему, потому что только после того, как они были созданы, только ИТ-операции имеют доступ к сценариям установки для конкретной среды.

Ответ 6

@n0rm1e: не уверен, что tomcat предоставляет какое-либо решение для вашей проблемы. Но одним из возможных решений может быть: - создайте ant script со следующими шагами:

i) Проверьте наличие файла .xml в каталоге [имя-engine]/[server-name]. Если он существует, возьмите резервную копию этого/переименовать его.

ii) скопируйте свой файл войны в tomcat webapps. Перезапустите сервер tomcat.

iii) скопируйте резервный файл конфигурации обратно в каталог [имя-engine]/[server-name]