Васильев Андрей Михайлович, 2024
Версии презентации
Примерно каждые полгода выходит новая версия. Тематика последних выпусков — расширение списка поддерживаемых платформ и переход на унифицированный компилятор
Мы будем рассматривать классический вариант — разработку приложений под JVM
flowchart LR kotlin["Исходный код на Kotlin"] java["Исходный код на Java"] kotlin-jvm("Компилятор Kotlin\nдля JVM") javac("Компилятор Javac") kotlin-class[".class-файлы"] java-class[".class-файлы"] jvm("Виртуальная машина\nJVM") kotlin --> kotlin-jvm --> kotlin-class --> jvm java --> javac --> java-class --> jvm
List
, Map
)За исключением конфигурации системы сборки минимальное приложение состоит только лишь из функции:
fun main() {
println("Я работаю!")
}
fun
Рассмотрим основы синтаксиса языка Kotlin
Реализуем небольшое приложение, которое позволит:
Рассмотрим основы работы с функциями в Kotlin
Рассмотрим вопрос null-безопасности в Kotlin
Принципиальная схема работы шаблонизатора
flowchart LR renderer(Шаблонизатор) template[Шаблон] base_template[Базовый шаблон] partial[Частичный шаблон] data[Данные\nдля отображения] text[Текст] base_template --> template partial --> template template --> renderer data --> renderer renderer --> text
Шаблоном может выступать код, написанный на языке Kotlin, но лучше использовать специализированные языки для данной предметной области
Pebble — шаблонизатор для JVM, синтаксически схожий с Twig и Jinja
Для использования шаблонизатора необходимо:
Для подключения библиотеки Pebbletemplates необходимо в файле build.gradle
в разделе dependencies
добавить следующую строку:
implementation 'io.pebbletemplates:pebble:3.2.2'
При добавлении библиотеки старайтесь всегда выбирать актуальные выпуски, не содержащие критических уязвимостей. Для поиска последней версии можно воспользоваться, напирмер mvnrepository.com
Изначально IDEA не поддерживает редактирование Pebble, однако существует расширение
.peb
, которые находятся в каталоге с ресурсами приложенияsrc/main/resources
Создадим шаблон-раскладку, которая будет являться базой для всех других страниц и назовём её layout.peb
:
<html>
<head>
<title>{% block title %}Сайт{% endblock %}</title>
</head>
<body>
<div id="content">
{% block content %}{% endblock %}
</div>
<div id="footer">
{% block footer %}
Copyright 2000-3088
{% endblock %}
</div>
</body>
</html>
Создадим шаблон для стартовой страницы и назовём его home.peb
:
{% extends "layout.peb" %}
{% block title %} Стартовая страница {% endblock %}
{% block content %}
<h1>Стартовая страница</h1>
<p>С очень важным содержимым</p>
<p>Время создания {{ time | date("yyyy-MM-dd HH:mm") }}</p>
{% endblock %}
{% %}
определяет места вызова управляющих конструкций Pebble {{ }}
определяет места для вывода результатов выражения в строкуblock
определяет места в раскладке для расширенияextends
позволяет наследовать один шаблон от другогоdate
позволяет преобразовывать даты в формат, удобный дляtime
— данные для отображения на страницеval engine = PebbleEngine.Builder().build() // Создаём шаблонизатор
val template = engine.getTemplate("home.peb") // Компилируем шаблон home.peb
val data = mapOf("time" to LocalDateTime.now()) // Формируем данные
val writer = StringWriter()
template.evaluate(writer, data) // Записать сформированную шаблоном
println(writer)
По умолчанию если шаблону не передать данные, то он просто проигнорирует их отсутствие
<html>
<head>
<title>Пример шаблона</title>
</head>
<body>
<p>Имя: {{ model.name }}</p>
<p>День рождения: {{ model.birthDate | date("yyyy-MM-dd") }}
</body>
</html>
{{ SOURCE | FILTER-1 | FILTER-2 }}
При обращении к полю переменной model.data
внутри шаблона Pebble попытается у переданного объекта вызвать следующие методы:
model
является словарём (наследником Map
), то будет вызван метод model.get("data")
model.getData()
model.isData()
model.hasData()
model.data()
model.data
Если в переменной list
содержится список, то к его полям можно обращаться с помощью list[0]
вместо list.get(0)
Если возвращённое значение на каком-то этапе будет null
, то шаблонизатор вернёт пустую строку
Шаблонизаторы поддерживает работу и со списками данных
class Event(val start: LocalDateTime, val description: String)
class EventsList(val events: List<Event>)
Шаблон для отображения списка событий:
{% for event in model.events %} // model содержит ссылку на объект EventsList
<h3>Событие {{ event.description }}</h3>
<p>Начало события: {{ event.start | date("yyyy-MM-dd HH:mm",
timeZone="UTC") }}</p>
{% else %}
<p>События не описаны</p>
{% endfor %}
Управляющие конструкции, вывод которых не должен попасть в текст документа, помещаются внутри {% %}
{% if category == "news" %}
{{ news }}
{% elseif category == "sports" %}
{{ sports }}
{% else %}
<p>Пожалуйста укажите категорию</p>
{% endif %}
and
— логическое Иor
— логическое ИЛИnot
— логическое отрицание()
— группировкаВ рамках условных выражений Pebble позволяет вызывать операцию is
и связывать её с проверками:
{% if 3 is odd %}
3 является нечётным числом
{% endif %}
При использовании оператора можно проверить отрицание проверки:
{% if name is not null %}
Имя не указано!
{% endif %}
Шаблонизатор Pebble поддерживает концепцию иерархических шаблонов
Базовый шаблон, например layout.peb
:
<html>
<body>
<div id="content">
{% block content %} {% endblock %}
</div>
<div id="footer">
{% block footer %} Default content {% endblock %}
</div>
</body>
</html>
Шаблон-расширение:
{% extends "./layout.peb" %}
{% block content %} Содержимое {% endblock %}
Помимо иерархического разделения Pebble поддерживает включение одних шаблонов в другие
<div class="sidebar">
{% include "advertisement.html" %}
</div>