Васильев Андрей Михайлович, 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>