Первый взгляд на веб-фреймворк без JavaScript
Scala — сильный статически типизированный язык программирования общего назначения, поддерживающий объектно-ориентированное и функциональное программирование. Play — это веб-фреймворк, который создает веб-приложения на Scala и Java. Play поставляется с Twirl, механизмом шаблонов на основе Scala, который имеет следующие преимущества:
- Компактный, выразительный и плавный: он сводит к минимуму количество символов и нажатий клавиш, необходимых в файле, и обеспечивает быстрый и плавный рабочий процесс кодирования.
- Простота в освоении: в нем есть минимум концепций для изучения, помимо конструкций Scala и знаний HTML.
- Не новый язык: это просто Scala + HTML.
- Редактируется в любом текстовом редакторе: простого редактора должно быть достаточно для продуктивной работы с кодом.
Play — это веб-фреймворк, не использующий JavaScript, и он рендерится на стороне сервера. Мы собираемся изучить, как работает веб-приложение Play.
Настройка игровой среды
Lightbend Tech Hub предлагает загружаемые примеры Play для Java и Scala. Обучение на примере — это эффективный способ мгновенно подготовить среду.
Это ссылка для загрузки примера, Play Scala Hello World. Разархивируйте загруженный файл play-samples-play-scala-hello-world-tutorial.zip в локальный каталог.
Play требует Java и sbt с некоторыми требованиями к версии:
- Java Software Developer’s Kit (SE) 1.8 или выше, который можно скачать здесь.
sbt1.3.4 или более поздней версии, которая включена в zip-файл. Как вариант, его можно скачать здесь.
sbt — это интерактивный инструмент сборки для Scala, Java и т. д. Он работает на JVM.
Проверьте версии, чтобы убедиться, что Java и sbt соответствуют требованиям.
% pwd /Users/jenniferfu/play-samples-play-scala-hello-world-tutorial % java --version openjdk 11.0.11 2021-04-20 OpenJDK Runtime Environment AdoptOpenJDK-11.0.11+9 (build 11.0.11+9) OpenJDK 64-Bit Server VM AdoptOpenJDK-11.0.11+9 (build 11.0.11+9, mixed mode) % sbt --version sbt version in this project: 1.7.2 sbt script version: 1.6.2
Выполнить sbt run:
% sbt run [info] welcome to sbt 1.7.2 (AdoptOpenJDK Java 11.0.11) [info] loading project definition from /Users/jenniferfu/play-samples-play-scala-hello-world-tutorial/project/project [info] loading settings for project play-samples-play-scala-hello-world-tutorial-build from plugins.sbt,scaffold.sbt ... [info] loading project definition from /Users/jenniferfu/play-samples-play-scala-hello-world-tutorial/project [info] loading settings for project root from build.sbt ... [info] __ __ [info] \ \ ____ / /____ _ __ __ [info] \ \ / __ \ / // __ `// / / / [info] / / / /_/ // // /_/ // /_/ / [info] /_/ / .___//_/ \__,_/ \__, / [info] /_/ /____/ [info] [info] Version 2.8.18 running Java 11.0.11 [info] [info] Play is run entirely by the community. Please consider contributing and/or donating: [info] https://www.playframework.com/sponsors [info] --- (Running the application, auto-reloading is enabled) --- [info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000 (Server started, use Enter to stop and go back to the console...)
Пример доступен из браузера по адресу http://localhost:9000.

Вот рабочий процесс:
- Браузер запрашивает корневой URI
/с HTTP-сервера, используя методGET. - Внутренний HTTP-сервер Play получает запрос.
- Play разрешает запрос, используя файл
routes, который сопоставляет URI с методами действия контроллера. - Метод действия отображает страницу
index, которая является шаблоном Twirl. - HTTP-сервер возвращает ответ в виде HTML-страницы.
Архитектура модель-представление-контроллер
Приложение Play использует Model-View-Controller (MVC), широко используемый архитектурный шаблон программного обеспечения для разработки пользовательских интерфейсов (UI).

- Модель является центральным компонентом выкройки. Это хранилище динамических данных приложения, независимое от пользовательского интерфейса.
- Представление — это любое представление информации, состоящее из заголовка, нижнего колонтитула, боковой панели, представления содержимого и/или других компонентов.
- Контроллер принимает ввод и преобразует его в команды для модели или представления.
Дерево исходного кода приложения Play
Разархивированный play-samples-play-scala-hello-world-tutorial выглядит так:
play-samples-play-scala-hello-world-tutorial ├── README.md ├── .g8 ├── app │ ├── controllers │ └── views ├── conf ├── logs │ └── application.log ├── project ├── public │ ├── images │ ├── javascripts │ └── stylesheets ├── sbt-dist ├── scripts │ └── test-sbt ├── target ├── build.sbt ├── sbt └── sbt.bat
play-samples-play-scala-hello-world-tutorial: это каталог проекта для приложения Play.README.md: Это файл README, в котором описаны требования к проекту и этапы выполнения..g8: это каталог, сгенерированныйplay-scala-seed.g8, шаблоном для создания сида проекта Play в Scala. Этот шаблон был использован для создания этого проекта.app: это каталог, содержащий код MVC, где находятся все исполняемые артефакты, включая исходный код Java и Scala, шаблоны и исходники скомпилированных ресурсов. В этом примере он содержит два пакета,controllersиviews. При наличии внешнего хранилища данных можно добавить пакетmodels. Кроме того, можно добавить пакетserviceиutils.conf: это каталог, содержащий конфигурацию приложения, включаяroutes.logs: это каталог, содержащий журналы, гдеapplication.log— файл журнала по умолчанию.project: это каталог, содержащийsbtфайлов конфигурации.public: это каталог для статических ресурсов, обслуживаемых непосредственно веб-сервером. Есть три подкаталога:images,javascriptsиstylesheets.sbt-dist: это каталог, содержащий распространяемый файлsbt.scripts: это каталог, содержащийsbtскриптов, где скриптtest-sbtвыполняет тесты с использованиемsbt.target: это каталог, содержащий сгенерированный код и документы API.build.sbt: это скрипт сборки, который выполняет проект в текущем каталоге (строка 1 ниже) с указанным плагином (строка 2) и настройками (строки 3–17). Обычной практикой является объявление отложенной загрузки проекта (строка 1).
sbt: это исполняемый файл, который вызывает распределенный скриптsbtс более чем 600 строками кода.
#!/usr/bin/env bash ./sbt-dist/bin/sbt "$@"
Ниже приводится использование sbt:
Usage: `basename "$0"` [options]
-h | --help print this message
-v | --verbose this runner is chattier
-V | --version print sbt version information
--numeric-version print the numeric sbt version (sbt sbtVersion)
--script-version print the version of sbt script
-d | --debug set sbt log level to debug
-debug-inc | --debug-inc
enable extra debugging for the incremental debugger
--no-colors disable ANSI color codes
--color=auto|always|true|false|never
enable or disable ANSI color codes (sbt 1.3 and above)
--supershell=auto|always|true|false|never
enable or disable supershell (sbt 1.3 and above)
--traces generate Trace Event report on shutdown (sbt 1.3 and above)
--timings display task timings report on shutdown
--sbt-create start sbt even if current directory contains no sbt project
--sbt-dir <path> path to global settings/plugins directory (default: ~/.sbt)
--sbt-boot <path> path to shared boot directory (default: ~/.sbt/boot in 0.11 series)
--ivy <path> path to local Ivy repository (default: ~/.ivy2)
--mem <integer> set memory options (default: $sbt_default_mem)
--no-share use all local caches; no sharing
--no-global uses global caches, but does not use global ~/.sbt directory.
--jvm-debug <port> Turn on JVM debugging, open at the given port.
--batch disable interactive mode
# sbt version (default: from project/build.properties if present, else latest release)
--sbt-version <version> use the specified version of sbt
--sbt-jar <path> use the specified jar as the sbt launcher
# java version (default: java from PATH, currently $(java -version 2>&1 | grep version))
--java-home <path> alternate JAVA_HOME
# jvm options and output control
JAVA_OPTS environment variable, if unset uses "$default_java_opts"
.jvmopts if this file exists in the current directory, its contents
are appended to JAVA_OPTS
SBT_OPTS environment variable, if unset uses "$default_sbt_opts"
.sbtopts if this file exists in the current directory, its contents
are prepended to the runner args
/etc/sbt/sbtopts if this file exists, it is prepended to the runner args
-Dkey=val pass -Dkey=val directly to the java runtime
-J-X pass option -X directly to the java runtime
(-J is stripped)
-S-X add -X to sbt's scalacOptions (-S is stripped)
In the case of duplicated or conflicting options, the order above
shows precedence: JAVA_OPTS lowest, command line options highest.
@JenniferFuBook
Add heading textAdd bold text, <Cmd+b>Add italic text, <Cmd+i>
Add a quote, <Cmd+Shift+.>Add code, <Cmd+e>Add a link, <Cmd+k>
Add a bulleted list, <Cmd+Shift+8>Add a numbered list, <Cmd+Shift+7>Add a task list, <Cmd+Shift+l>
Directly mention a user or team
Reference an issue or pull request
Leave a comment
sbt.bat: это исполняемый файл, который вызывает скрипт запуска распределенногоsbtс более чем 900 строками кода.
@REM SBT launcher script .\sbt-dist\bin\sbt.bat %*
Контроллеры игрового приложения
Контроллер управляет приложением MVC на основе рабочего процесса. Он принимает ввод и преобразует его в команды для модели или представления. Контроллер в Play — это не что иное, как объект, который генерирует Action значений. Контроллеры воспроизведения обычно определяются как классы, чтобы использовать преимущества внедрения зависимостей.
app/controllers — рекомендуемый каталог для контроллеров. Из коробки есть один контроллер, HomeController.scala.
controllers └── HomeController.scala
Вот app/controllers/HomeController.scala:
- В строке 1 пакет
controllersсоздается путем объявления его в верхней части файла Scala. Было бы удобно назвать пакет так же, как каталог, содержащий файл Scala. Однако Scala не зависит от расположения файлов. - В строке 3 импортируется все содержимое пакета
javax.inject.javax— это соглашение об именах для расширения JRE. Приведенный выше код имеет синтаксис Scala 2:import javax.inject._. В Scala 3 это будет записано какimport javax.inject.*. - В строке 4 импортируется все содержимое пакета
play.api. - В строке 5 импортируется все содержимое пакета
play.api.mvc. - В строках 11–33 создается класс с одноэлементной записью (строка 11). Он вызывает идиоматический API Play для
Action, расширяяAbstractController(строка 12). Этот контроллер определяет три действия для трех маршрутов:index(/),explore(/explore) иtutorial(/tutorial). - В строках 21–23 он определяет метод
index, который представляет собойAction, возвращающийOk(views.html.index()). Он генерирует HTML-страницу, определеннуюindex.scala.html, шаблоном Twirl вviews. - В строках 25–27 он определяет метод
explore, который представляет собойAction, возвращающийOk(views.html.explore()). Он генерирует HTML-страницу, определеннуюexplore.scala.html, шаблоном Twirl вviews. - В строках 29–31 он определяет метод
tutorial, который представляет собойAction, возвращающийOk(views.html.tutorial()). Он создает HTML-страницу, определеннуюtutorial.scala.html, шаблоном Twirl вviews.
Просмотры приложения Play
Представление производит ответ для браузера. Он получает данные от модели и представляет их браузеру для отображения. Это может быть полное представление маршрута или подвид, составляющий целое представление.
app/views — рекомендуемый каталог для представлений. По умолчанию есть несколько файлов представлений, написанных как шаблоны Twirl с расширениями .scala.html.
views ├── main.scala.html ├── commonSidebar.scala.html ├── index.scala.html ├── explore.scala.html └── tutorial.scala.html
main.scala.html отображает head и body. Он принимает два аргумента: String для заголовка страницы и объект Html для вставки в тело страницы. Другие шаблоны Twirl используют его для создания HTML-страницы.
Вот app/views/main.scala.html:
- В строке 7 он определяет конструктор с двумя аргументами:
titleиcontent. - В строках 9–32 это шаблон HTML, где он определяет
head(строки 12–20) иbody(строки 22–30). - В строке 13
@titleявляется динамическим значением, которое вычисляется из аргументаtitle. - В строках 23–28 определяется заголовок страницы.
- В строке 29
@contentявляется динамическим значением, которое вычисляется из аргументаcontent.
Включая этот шаблон, на странице будет отображаться следующий заголовок:

commonSidebar.scala.html определяет main.scala.html, который не принимает аргументов.
Вот app/views/commonSidebar.scala.html:
- В строке 1 он определяет конструктор без аргументов.
- В строке 2 он устанавливает
versionв значениеplay.core.PlayVersion.current. - В строках 3–8 он определяет список оглавления, где
@routes.HomeController.index()(строка 5),@routes.HomeController.explore()(строка 6) и@routes.HomeController.tutorial()(строка 7) — функции маршрута. - В строках 9–16 он определяет список связанных ресурсов, где
@version(строка 11) — динамическое значение.
Вот дисплей пользовательского интерфейса:

index.scala.html — это шаблон Twirl, который вызывается маршрутом index (/).
Вот app/views/index.scala.html:
- В строке 1 он определяет конструктор без аргументов.
- В строках 3–71 директива
main(строка 3) вызывает шаблонmain,main.scala.html, с двумя параметрами.
- заголовок:"Welcome"- содержание: строки 4–71, где
@commonSidebar()(строка 66) — это общая боковая панель, определенная вcommonSidebar.scala.html.
Вот дисплей пользовательского интерфейса:

explore.scala.html — это шаблон Twirl, который вызывается маршрутом explore (/explore).
Вот app/views/explore.scala.html:
- В строке 1 он определяет конструктор без аргументов.
- В строках 3–90 директива
main(строка 3) вызывает шаблонmain,main.scala.html, с двумя параметрами для создания страницы.
- заголовок:"Hello World"- содержание: строки 4–90, где
@commonSidebar()(строка 84) — это общая боковая панель, определенная вcommonSidebar.scala.html.
Вот дисплей пользовательского интерфейса:

tutorial.scala.html — это шаблон Twirl, который вызывается маршрутом tutorial (/tutorial).
Вот app/views/tutorial.scala.html:
- В строке 1 он определяет конструктор без аргументов.
- В строках 3–162 директива
main(строка 3) вызывает шаблонmain,main.scala.html, с двумя параметрами для создания страницы.
- заголовок:"Hello World"- содержание: строки 4–162, где
@commonSidebar()(строка 157) — это общая боковая панель, определенная вcommonSidebar.scala.html.
Вот дисплей пользовательского интерфейса:

Поскольку шаблоны отображаются на сервере, нет необходимости использовать REST API для конечных точек. Шаблоны Twirl могут получать доступ к моделям через код Scala.
Конфигурация игрового приложения
conf — это каталог, содержащий конфигурацию приложения (скомпилированную) и другие нескомпилированные ресурсы на classpath. Из коробки есть эти файлы.
conf ├── routes ├── application.conf ├── logback.xml └── messages
Маршрутизатор — это компонент, отвечающий за преобразование каждого входящего HTTP-запроса в действие контроллера. HTTP-запрос рассматривается платформой MVC как событие. Это событие содержит две основные части информации:
- Путь запроса, включая строку запроса
- Метод HTTP (GET, POST, PUT, DELETE и т. д.)
routes — это файл конфигурации, используемый маршрутизатором. Он разрешает входящий HTTP-запрос, находя правильный URI и затем сопоставляя его с методом действия контроллера. Один и тот же запрос может соответствовать многим маршрутам.
Вот app/conf/routes:
- В строке 7 для метода GET маршрута
indexвызывается метод/,HomeControllerindex. - В строке 8 для метода GET маршрута
exploreвызывается метод/explore,HomeControllerexplore. - В строке 9 для метода GET маршрута
tutorialвызывается метод/tutorial,HomeControllertutorial. - В строке 13 для метода GET маршрута актива,
/assets/*file, вызывается методversionedвстроенного контроллераAssetsс путем (/public) и именемfile.*file— это динамическая часть, соответствующая регулярному выражению.*.
Перейдите по URL-адресу http://localhost:9000/assets/images/play-stack.png, и появится следующее изображение:

Что делать, если есть конфликт в routes?
Будет использоваться первый маршрут в порядке объявления.
Что делать, если в routes есть ошибка?
Ошибка маршрута будет отображаться непосредственно в браузере, поскольку этот файл был скомпилирован.
Вот пример несопоставленного маршрута /xyz:

При необходимости API REST можно настроить в маршрутах. В этой статье объясняется, как реализовать REST API в маршрутах.
Помимо routes, есть и другие файлы конфигурации, application.conf, logback.xml и messages.
application.conf: Это основной файл конфигурации, который определяет функции, токены, файлы cookie, пул соединений, пулы потоков, ведение журнала, кеш и т. д.logback.xml: Это файл конфигурации журнала. Play используетSLF4Jдля ведения журнала, поддерживаемогоLogback, в качестве механизма ведения журнала по умолчанию.messages: Это каталог сообщений для I18N.
Заключение
Play — это веб-фреймворк, который создает веб-приложения с помощью Scala и Java. Веб-страницы отображаются на стороне сервера и пишутся с помощью шаблонов Twirl.
Для разнообразия мы изучили веб-фреймворк без JavaScript. Все они манипулируют HTML, но их синтаксис и терминология различаются.
Все дороги ведут к веб-приложениям.
Спасибо за прочтение.
Спасибо, С. Шрирам, Ноа Джексон и Сиддхартха Чинтхапалли, за работу со мной над веб-приложениями Play.
Want to Connect? If you are interested, check out my directory of web development articles.