Внедрение сервисов REST API в приложения выявило необходимость пересмотра структуры проектов (на уровне дерева файлов и папок).
Статья знакомит читателя с новой структурой проектов приложений и описывает основные шаги перевода проекта со старой, gwt-центричной структуры на новую, обеспечивающую независимость компонентов приложений.
Папка App
является корневой для разработки клиент-серверного приложения.
Приложение может иметь несколько независимых друг от друга реализаций клиентов и сервисов (сервисом здесь называется серверная часть приложения, бэкенд). Каждая реализация клиента или сервиса находится в отдельной папке, название которой начинается с соответствующего префикса
/App
/client-...
/client-...
/service-...
/service-...
/service-...
/service-...
Каждая реализация клиента или сервиса называется компонентом.
В совершенстве, разные компоненты независимы друг от друга: они могут быть построены на разных языках программирования и разных технологиях, и сборка каждого компонента происходит отдельно. Также каждый компонент имеет свой продукт (war, ear, javascript bundle), и продукты разных компонентов могут быть установлены на разных серверах и использоваться в разных окружениях.
Для идентификации компонентов на уровне структуры папок достаточно использовать наиболее лаконичный постфикс, однозначно идентифицирующий конкретный компонент и отличающий его от других
/App
/client-react // клиент на React/JS
/client-gwt // клиент на GWT/Java
/service-gwt // сервис на GWT/Java
/service-rest-jersey // сервис на Rest/Jersey/Java
/service-rest-spring // сервис на Rest/Spring/Java
/service-php // сервис на Soap/PHP
В случае, если у нескольких компонентов имеется общий код, следует выделять его в отдельный компонент, если возникают неоднозначности
/App
/service-java-core // бизнес-логика сервиса на java (общая для нескольких других компонент)
/service-java-rest-jersey // сервис на Rest/Jersey/Java, построенный на общем компоненте service-java-core
/service-java-rest-spring // сервис на Rest/Spring/Java, построенный на общем компоненте service-java-core
Однако такое архитектурное решение влечёт с неизбежностью взаимозависимости между компонентами, поэтому следует применять его только если это оправдано (например, при наличии объёмной прослойки общего кода бизнес-логики).
В действительности и в обозримом будущем для большинства приложений планируются только следующие компоненты:
/App
/client-react // клиент на React/JS
/gwt // клиент и сервис на GWT/Java
/service-rest // сервис на Rest/Jersey/Java
Здесь компонент /gwt
совмещает в себе клиентский и серверный код GWT (традиционно), при этом сохраняется историческое разделение клиентского и серверного кода на уровне java-пакетов
/App
/client-react
/gwt
/src/java/com/technology/jep/jepriashowcase
/client // клиент на GWT/Java
/server // сервис на GWT/Java
/shared // общая клиент-сервисная часть на GWT/Java
/service-rest
Внутри папки каждого компонента соблюдается структура, адекватная конкретной технологии.
Для gwt-компонента принимается без изменений историческая структура проекта, для компонента service-rest
-- структура Maven-стандартная
/App
/gwt // историческая структура
/src
/java
/html
/resources
/config
/lib
/test
/service-rest // структура проекта Maven
/src
/main
/java
/webapp
/test
/java
/target
Каждый компонент имеет свой сценарий сборки (для поддержания независимости компонентов). Результатом сборки является продукт, располагающийся внутри папки компонента
/App
/client-react
/build
/jepriashowcase-bundle.js // продукт
package.json // сценарий сборки
/service-rest
/target
jepriashowcase-service-rest.war // продукт
pom.xml // сценарий сборки
/gwt
/lib
jepriashowcase-gwt.war // продукт
build.xml // сценарий сборки
Исторически администрирование приложений на серверах велось посредством единых war
файлов (содержащих и клиентскую, и сервисную части). Для поддержания этого механизма помимо сборки каждого продукта в отдельности, производится общая сборка проекта, суть которого -- упаковать необходимые продукты отдельных компонентов в общий продукт.
Файлы и ресурсы, необходимые для общей сборки, лежат в корне проекта
/App
/client-react
/build
/jepriashowcase-bundle.js // продукт
package.json, ... // сценарии сборки
/service-rest
/target
jepriashowcase-service-rest.war // продукт
pom.xml, ... // сценарии сборки
/gwt
/lib
JepRiaShowcase-gwt.war // продукт
build.xml, ... // сценарии сборки
/lib // папка общего продукта (для обратной совместимости)
JepRiaShowcase.war // общий продукт, совмещающий отдельные продукты (имеет исторически сложившееся имя и расположение)
/webapp
/WEB-INF
web.xml // web.xml для общего продукта (является ручным объединением web.xml-файлов разных компонентов)
build.xml // сценарий сборки общего продукта (поддерживает исторические команды администрирования приложения)
dependency.properties // пропертисы для сборки общего продукта
deploy.properties // пропертисы для сборки общего продукта
Администрирование единого war
файла обеспечивает одновременное администрирование совмещённых в нём продуктов разных компонентов и создаёт единую точку входа в приложение через веб (по старому стилю).