Первый взгляд на веб-фреймворк без 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 или выше, который можно скачать здесь.
sbt
1.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
вызывается метод/
,HomeController
index
. - В строке 8 для метода GET маршрута
explore
вызывается метод/explore
,HomeController
explore
. - В строке 9 для метода GET маршрута
tutorial
вызывается метод/tutorial
,HomeController
tutorial
. - В строке 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.