3. О чём поговорим
Плагин kotlin-spring
Kotlin extensions для GenericApplicationContext
Kotlin extensions для RestTemplate
Нативная поддержка nullable-типов
Kotlin Script шаблоны
Spring 5 WebFlux 101
Kotlin extensions для Reactor
Kotlin DSL для WebFlux functional API
Привет!
Меня зовут Сергей. Я в тайне люблю Kotlin, но коллеги и девушка не знают об этом. Spring мне тоже нравится, а в пятой версии он станет ещё лучше.
Вот я и решил, почему бы не рассказать вам о том, как свести их вместе, тем более, что ребята из Pivotal добавляют поддержку Kotlin прямо во фреймворк.
Многое из того, о чём будем говорить далее может измениться к финальному релизу. Примеры кода собраны на SNAPSHOT-версиях Spring 5 M4 и могут поломаться уже завтра.
Код приложения написан на Kotlin изначально, если будут какие-то вопросы (может для кого-то это первое знакомство с этим прекрасным языком) - перебивайте, задавайте вопросы.
UPD: API действительно поменялось прямо между ивентами :)
Поднимите, пожалуйста, руки, кто пробовал писать приложения на Kotlin и Spring [Boot]?
В общем, если “скормить” @Configuration классы, написанные на Kotlin Spring’у, он будет ругаться на то, что они final. Да, в Kotlin все классы final by default.
Ещё одна проблема, о ней лишь вкратце, возникает при использовании Kotlin классов с различными фреймворками, которым нужен дефолтный конструктор без параметров в бинах, например JPA.
Но недавно JetBrains пошёл на уступку. Они написали несколько специальных плагинов - kotlin-allopen, kotlin-noarg, kotlin-spring - которые делают классы открытыми для наследования при наличии тех или иных аннотаций (настраиваемо), а также добавляют конструкторы по умолчанию.
По сути, kotlin-spring - это преднастроенный на аннотации @Component (@Configuration, @Controller, @RestController, @Service or @Repository), @Async, @Transactional, @Cacheable kotlin-allopen плагин.
Лично я не фанат этого решения (например, код со StackOverflow написанный с этим плагином не будет работать без него, т.е. один и тот же код ведёт себя по-разному) и в своём коде его использовать не буду, но пример покажу.
P.S. И не то, чтоб я часто копипастил со SO...
Незначительное улучшение, добавляющее 6 перегруженных методов (extensions) registerBean в класс GenericApplicationContext, а также позволяющее конфигурировать его с помощью лямбды c ресивером (такая специальная языковая конструкция, позволяющая писать крутые DSL).
Эти методы работают за счёт reified-типов в inline-функциях. reified типы позволяют “обходить” type erasure за счёт инлайнинга (подстановки), что убирает необходимость в рефлексии, ведь типы известны на этапе компиляции из контекста.
Полтора десятка расширений для всем известного RestTemplate, в основном снимающие надобность в последнем параметре-типе (Person.class). Как и в случае расширений для GenericApplicationContext, вся магия кроется в reified-типах.
Также в Spring 5 появился новый класс - WebClient - с приятным синтаксисом и поддержкой Mono / Flux из коробки.
Почти три года назад в Spring появилась поддержка java.util.Optional при внедрении зависимостей, а также в MVC фреймворке для необязательных параметров. И вот, наконец, мы дождались такой же поддержки Kotlin nullable-типов.
В Spring 4.3 появилась поддержка шаблонов на языках, поддерживающих JSR-223 (например, JavaScript c движком Nashhorn).
Kotlin 1.1 вводит поддержку JSR 223.
Напрашивается вывод…
Можно использовать как простые String templates, так и библиотеки типа kotlinx.html (рекомендую).
Правда, пока что нужно сконфигурировать кое-какие вещи самому, надеюсь в будущем упростят. А ещё, эта штука жутко сырая, течёт как Амазонка, сыпет непонятными ошибками на Windows и компилирует шаблоны при каждом вызове!
На самом деле, до этого речь шла о не очень впечатляющих вещах, неправда ли?
Может быть кто-нибудь уже смотрел в сторону Spring 5? Работал с RxJava / Spring Reactor?
Так вот, Spring 5 предлагает разработчикам новый подход к написанию веб-приложений, не основанный на стандартном Servlet Engine. Это новый реактивный (функциональный, неблокирующий) подход, называемый WebFlux, и за ним стоит Spring Reactor / Reactive Streams.
Функциональный потому что логика обработки данных описывается в декларативном, функциональном стиле как композиция каких-то преобразований (функций). Само описание потока не вызывает никаких действий. Поток лишь реагирует на данные по мере их поступления.
Неблокирующий потому что предполагается использовать его с неблокирующими API - NIO, CompletableFutures, AsyncRestTemplate, ReactiveMongoTemplate избегая блокировок основных потоков, вынося работу в пулы.
На самом деле, такой же код можно было бы написать и с использованием коллбеков, но не так удобно.
WebFlux умеет работать на Servlet 3.1+ или на Netty / Undertow. Но вам не нужно париться - просто подключите Spring Boot стартер.
Publisher публикует данные
Subscriber подписывается на Publisher
Subscriber может управлять потоком данных (или отписаться) через Subscription
Processor это комбинация Publisher и Subscriber, служит для создания потоков данных (операторов), где один и тот же класс может выступать в обеих ролях.
Reactor - это имплементация Reactive Streams, добавляющая некоторые фитчи.
Mono и Flux это паблишеры, публикующие 0..1 или 0..N элементов соответственно.
Например findById - это Mono, findAll, searchByTerm - Flux.
Откуда возьмутся эти Flux и Mono? Библиотеки будут предоставлять RS API (например, реактивный драйвер Mongo) или же их можно создать самому из других, “привычных” объектов.
Проект reactor-kotlin предоставляет несколько расширений для преобразования одиночных значений, массивов, коллекций, стримов, фьюч в Mono и Flux.
К сожалению, у меня что-то не ужились оба стиля в одном контексте :( И я расстроился.
А потом я прочитал доку: “Your Spring Boot WebFlux application should use the RouterFunction or the RequestMapping approach, it is currently not possible to mix them in the same application.”
¯\_(ツ)_/¯
Прикольная штука, но мне что-то не зашло, да и API ещё не устаканился.