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

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

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

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

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

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

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

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

Спасибо

Ответы [ 6 ]

42 голосов
/ 26 августа 2011

Решение простое: не помещайте конфигурацию в ваш context.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. Важно, что это нужно сделать только один раз для каждого сервера, а не при повторном развертывании.

В нашей конфигурации пружины, чтобы определить 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.

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

11 голосов
/ 24 августа 2011

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

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, но, поскольку мы используем Spring4 LogConfigListener, оно не будет запускаться из невзорванного файла .war. Tomcat не взрывает файлы .war, помещенные вне папки appBase (webapps).

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

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

5 голосов
/ 07 ноября 2015

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

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

Например, у меня есть веб-приложение 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");
4 голосов
/ 28 августа 2011

Ссылаясь на Документация Apache Tomcat 5.5 :

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

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

1 голос
/ 23 августа 2011

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

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

ii) скопируйте свой военный файл в веб-приложения tomcat.Перезапустите сервер Tomcat.

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

1 голос
/ 22 августа 2011

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...