Внедрение сервисов 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
файла обеспечивает одновременное администрирование совмещённых в нём продуктов разных компонентов и создаёт единую точку входа в приложение через веб (по старому стилю).