Могу ли я использовать один военный файл в нескольких средах? Нужно ли мне? - PullRequest
27 голосов
/ 28 октября 2009

У меня на работе есть веб-приложение на Java, и я хотел бы упростить процесс развертывания в средах DEV, QA и PROD.

Приложение считывает ряд свойств при запуске, а файлы свойств различаются для dev, qa и prod. Всякий раз, когда я хочу выполнить развертывание в определенной среде, я помещаю файл свойств среды в папку своего приложения, собираю войну и затем развертываю его на одном из трех серверов tomcat 5.5.

То, что я хотел бы сделать, - это иметь один .war, который имеет свойства для всех сред, и заставить приложение опрашивать веб-сервер в процессе инициализации, чтобы выяснить, в какой среде находится приложение, и, следовательно, какие свойства загрузить. Есть ли простой способ (или, если это невозможно, стандартный способ) сделать это?

Ответы [ 8 ]

17 голосов
/ 28 октября 2009

Это действительно зависит от того, для чего вы используете эти свойства.

Некоторые (например, источник данных) можно настроить в самом контейнере ( Tomcat 5.5. Ресурсы JNDI , см. Также раздел Источники JDBC).

Другие (специфичные для приложения) действительно могут быть свойствами. В этом случае ваш выбор:

  1. Объединить свойства в файле WAR и загрузить соответствующее подмножество на основе какого-либо внешнего переключателя (либо переменной среды, либо свойства JVM)
  2. Настройте процесс развертывания на каждом из ваших серверов, где распаковывается war и файл свойств (расположенный в предопределенном месте на этом сервере и специфичный для этого сервера) копируется в WEB-INF/classes (или другое подходящее место).

Что касается "это желаемая цель" - да, я так думаю. Наличие единой WAR для тестирования в QA / staging и последующего развертывания в производство сокращает промежуточный этап и, таким образом, оставляет меньше шансов на ошибки.

Обновление (на основе комментария):

Элемент # 1 выше относится к фактической переменной среды (например, что-то, что вы установили через SET ENV_NAME=QA в Windows или ENV_NAME=QA; export ENV_NAME в Linux). Вы можете прочитать его значение из вашего кода, используя System.getenv() и загрузить соответствующий файл свойств:

String targetEnvironment = System.getenv("TARGET_ENV");
String resourceFileName = "/WEB-INF/configuration-" + targetEnvironment + ".properties";
InputStream is = getServletContext().getResourceAsStream(resourceFileName);
Properties configuration = new Properties();
configuration.load(is);

Но да, вместо этого вы можете определить скалярное значение через JNDI ( см. Записи окружения в Tomcat doc ) вместо этого:

<Context ...>
  <Environment name="TARGET_ENV" value="DEV" type="java.lang.String" override="false"/>
</Context>

и прочитайте его в своем приложении через

Context context = (Context) InitialContext().lookup("java:comp/env");
String targetEnvironment = (String) context.lookup("TARGET_ENV");
// the rest is the same as above

Дело в том, что если вы все равно будете использовать JNDI, вы также можете отказаться от своих файлов свойств и все настроить через JNDI. Ваши источники данных будут доступны вам как фактические ресурсы, а базовые свойства останутся скалярами (хотя они будут безопасны по типу).

В конечном итоге вам решать, какой путь лучше для ваших конкретных потребностей; у обоих есть свои плюсы и минусы.

6 голосов
/ 28 октября 2009

То, что вы делаете, это несчастный случай, ожидающий случиться ... Однажды война DEV закончится на сервере de PROD, и по некоторым законам, превосходящим все законы природы, эта проблема будет обнаружена в 2 часа ночи. Не могу объяснить, почему это так, но когда-нибудь это произойдет. Так что одна война, на мой взгляд, определенно хорошая идея.

Вы можете установить системное свойство в соответствующей JVM (-Dcom.yourdomain.configpath = / where / you / store / configfiles) и получить это свойство с помощью

String value = System.getProperty("com.yourdomain.configpath", "defaultvalue_if_any"); 

Значение по умолчанию может указывать где-то внутри войны (WEB-INF / ...), или, если нет значения по умолчанию, может использоваться для создания некоторого шума при загрузке, чтобы предупредить о неправильной конфигурации). Также обратите внимание, что этот метод не зависит от платформы, поэтому ваш компьютер может быть Windows-сервером, а сервер - Linux-машиной, он может справиться с обоими. Обычно мы создаем подкаталог для каждого приложения в этом configpath, так как несколько приложений используют эту систему на сервере, и мы хотим, чтобы все было в порядке.

В качестве дополнительного бонуса вы не рискуете таким образом удалить файлы свойств, вручную настроенные на сервере PROD. Только не забудьте указать путь, в котором хранятся файлы, в сценарии резервного копирования.

4 голосов
/ 28 октября 2009

Я думаю, что один военный файл - хороший путь, потому что приятно иметь уверенность, что двоичный файл, который вы тестировали в DEV, точно такой же, как в Production. То, как мы это делаем, мы храним конфигурации в отдельном файле свойств, вне войны, но в пути к классам сервера приложений.

Если вы хотите сохранить все свойства внутри войны (что облегчает развертывание, потому что вам не нужно также развертывать файл свойств), вы можете сохранить один файл свойств в classpath, который идентифицирует сервер тип окружения и используйте его для ввода значений в файле свойств в вашем .war-файле. Файл внешних свойств также может быть хорошим способом использования некоторых высокоуровневых конфигураций, которые мало меняются и используются во многих военных файлах.

1 голос
/ 28 октября 2009

Установите при запуске Systemproperty, который указывает на местоположение файла свойств, а затем в вашем приложении выберите это свойство и загрузите настройки. Еще одна вещь, которую я делаю, - это наличие файла двух свойств, например, default.properties и external.properties. Они содержат те же свойства, но default.properties содержит настройки по умолчанию (работает большую часть времени), этот файл отправляется в войну. Затем, если вы развернете в env. вы ищите external.properties, если найдено, что используется, если нет, то вы откатываетесь к default.properties. Это обеспечивает хороший способ переопределения свойств при необходимости, но также имеет настройки по умолчанию. Это работает во многих моих развертываниях, но может не сработать в вашем сценарии.

1 голос
/ 28 октября 2009

Я предпочитаю один EAR или один WAR подход. С точки зрения безопасности есть что-то обнадеживающее и часто требующее того же самого EAR, который был только что протестирован, и перевода его непосредственно в следующее состояние (test> Production).

Существует также много опций, помимо файлов свойств, предоставляемых контейнером. Часто контейнер имеет приятный интерфейс для поддержки этих значений и ресурсов, когда вы мертвы и ушли.

Существует бесчисленное множество примеров использования базы данных с поддержкой ResourceBundle .

Например, среда Spring имеет несколько механизмов, позволяющих сделать это без особых усилий. Начиная с PropertyPlaceholderConfigurer

1 голос
/ 28 октября 2009

Вероятно, самым простым способом было бы установить переменную среды, которая различается между службами приложения, и использовать ее для определения файла свойств, который нужно прочитать.

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

0 голосов
/ 31 января 2018

Один билд (война), безусловно, правильный подход. Однако, когда дело доходит до конфигурации, специфичной для среды, лучший способ - убедиться, что все файлы конфигурации .properties не должны передаваться во все среды. например Файлы свойств PROD должны быть скопированы в DEV или UAT. Также следует избегать пружинных профилей, поскольку они приводят к запутанному управлению конфигурацией.

0 голосов
/ 28 октября 2009

Абсолютно одна ВОЙНА - лучший путь. Задайте ресурсы, используя одинаковые имена JNDI в каждой среде, и если вам нужно определить, в какой среде вы находитесь в целях бизнес-логики, используйте свойство System при запуске Tomcat.

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