Доброго времени суток всем. Хотел бы представить вашему вниманию небольшое описание новых возможностей Play 2. Речь в данной статье пойдет о play2 scala.
Для начала расскажу немного о себе и play. С 2008 по 2010 я работал в команде разработчиков play, тогда мы усиленно работали над коммюнитизацией play (версии 1.0 и 1.1). На данный монент я сменил команду но часто вижусь с моими прежними коллегами и продолжаю использовать play в большинстве проектов. Сам play вытек из одного проприетерного проекта, который мы реализовали для одного из крупнейших французских банков. Вообще, если кому интересно, я могу написать об истории play в отдельной статье.
Роль scala и java
Если раньше поддержка scala в play реализовалась в специальном модуле то начиная с версии 2, scala является полноправным членом фреймворка на ровне с java. Если быть точнее то можно сказать что многие кирпичики play 2 сделаны на scala и могут быть использованы в java.
Система построения проектов
Раньше в play была собственная система построения проектов реализованная в виде скриптов / классов на python, bash, batch. Позднее нашлись люди которые в конец осквернили мой любимый фреймворк и прикрутили к нему мувен (maven) в ввиде отдельного модуля. Теперь же вся система построения проектов строится на sbt + плагин play sbt (ну и немного bash, batch куда без них).
Консоль play
В новой версии play обзавелся настоящей консолью. Теперь у вас есть возможность компилировать, тестить, запускать ваш проект (итд) прямо из консоли. А в целом консоль play всего лишь надстройка над консолью sbt.
Контроллеры и действия
Теперь в play все ваши действия (actions) должны возвращать специальный тип — результат (result). В scala части для этого имеется специальный helper — action:
def index = Action {
Ok(«Hello world!»)
}
Это простой пример использования действия. Поверьте мне у вас есть возможность выполнять куда более сложные манипуляции.
Рутирование (routes)
Во второй версии не избежал изменений и механизм рутирования. Теперь вам явно нужно указывать ваши параметры http для каждого действия в файле routes.
GET / controllers.Application.index
POST /:id controllers.Application.new1(id:Int)
Если вы проектируете рут-карту до создания действий и контроллеров вы можете столкнутся с ошибками компиляции, поскольку вы указали несуществующие действия. В таком случае вы можете воспользоваться предопределенными действием — TODO которое возвращает 503 в случае обращения.
object Application extends Controller {
def index = TODO
def new1(id: Long) = TODO
}
Вид
Как вы могли видеть в play 2 был реализован новый движок скриптов вида базирующийся все так же на scala и схожий с ASP.NET Razor. Движок очень мощный и одновременно простой в изучении.
Модель
В play 2 в качестве модели у вас есть возможность использовать просто jdbc или же Anorm или что либо другое, например ScalaQuery или же если постараться то jpa, чего я бы вам не рекомендовал. Если вам интересно то я мог бы вынести в отдельную статью введение в Anorm.
Интеграция с Akka
Вы не узнаете асинхронную часть в play 2, она была переделана с использованием Akka 2.0. Вы можете конфигурировать вашу actor систему непосредственно в файле конфигурации или же если вам не нравится встроенная actor система вы можете использовать любую другую систему.
akka.default-dispatcher.core-pool-size-max = 64
akka.debug.receive = on
У вас все так же имеется возможность запускать задачи асинхронно только теперь это делается не по средствам аннотаций а немного подругому, так сказать все более в духе dsl.
Akka.system.scheduler.schedule(0 seconds, 30 minutes, testМе, «ме»)
Асинхронный HTTP
Поскольку вся внутренняя архитектура play построена на netty то благодаря этому мы имеем доступ к таким замечательным возможностям как WebSocket или асинхронное использование протокола HTTP. Иногда вам нужно выполнить какую либо ресурсоемкую операцию в одном из ваших контроллеров, именно для таких ситуаций вам и пригодится async HTTP. Все что вам нужно сделать в данном случае — это изменить тип результата в вашем действии с SimpleResult на AsyncResult.
def index = Action {
val promise = Akka.future { computation() }
Async {
promise.map(result => Ok(«Got result: » + result))
}
}
Работа с json
Так же в play 2 были добавлены доморощенные API для работы с json, на мой взгляд не самые удобные. Чтение json еще куда не шло (в простых случаях) но вот конвертирование из объектов в json, на мой взгляд очень хромает.
Чтение:
((Json parse string) «node1» «node2»).asOpt[String]
Построение:
Json toJson Seq(toJson(1), toJson(«Bob»), toJson(3), toJson(4))
Хотя у вас всегдя есть возможность использовать внешние библиотеки как и в ранних версиях play.
Global object
Global object выступает в роли бутстрап-класса для вашего приложения. Он может вклиниваться в такие события вашего приложения как onStart, onStop, onError, onActionNotFound итд. Это своего рода замена @OnApplicationStart и ко из async jobs play 1.*. Вот пример использования такого объекта:
object Global extends GlobalSettings {
override def onStart(app: Application) {
Logger.info(«Application has started»)
}
override def onStop(app: Application) {
Logger.info(«Application shutdown...»)
}
}
Тесты
Здесь скажу лишь по поводу части scala. Наконец то появилась возможность использовать стороннюю библиотеку для тестирования, а именно specs2 с поддержкой mockito. Помимо этого тестирование остается таким же удобным как и раньше.
Заключение
Данная статья представляет собой лишь поверхностный обзор возможностей фреймворка play 2. Если вам интересно то далее я могу представить вашему вниманию более детальные обзоры на такие темы как:
- Anorm и другие light orm в play2
- MVC play2 в детялях
- Play2 в продакшене
- Итд
Спасибо за внимание.
Автор: vba