Статьи

Написание модулей для Play 2, часть 1: Получите что-нибудь работающее

Пару недель назад я перенес Play! Framework 1.x версии Deadbolt для платформы Play 2, и был удивлен отсутствием информации о создании модулей. Эта тема была подробно рассмотрена в документации по Play 1.x, и это сделало создание модулей очень простым. Понятно, что нужно что-то делать — и это первая из трех частей серии о создании модулей и плагинов для Play 2.

Важно отметить, что это не окончательное руководство — это набор информации и техник, которые я использовал при работе над моими собственными модулями.

Я собираюсь предположить, что у вас уже есть работающая установка Play 2 — если у вас ее нет, зайдите на http://www.playframework.org/documentation/2.0/Install, чтобы узнать, как ее настроить.

В этой первой части мы рассмотрим основы создания и публикации модуля и добавления примера приложения. Следующие две части будут более подробно рассмотрены в плагинах, перехватчиках, тегах и других полезных инструментах.

Сначала небольшая заметка о разнице между модулем и библиотекой. В Play 1.x модуль был создан с использованием «play new-module» и распространялся через репозиторий модулей. Вплоть до Play 1.1 модули контролировались через записи application.conf, а библиотеки добавлялись локально. Начиная с версии 1.2, модули и библиотеки контролировались с помощью механизма управления зависимостями на основе Ivy. В обоих случаях, однако, была четкая концепция модуля (что-то тесно интегрированное с Play, которое следовало его соглашениям по структуре пакетов и т. Д.) И библиотеки (общая сторонняя библиотека).

В игре 2 линия размыта до некоторой степени. Модули теперь распределяются так же, как библиотеки, хотя Ivy или Maven, и структура пакета может быть произвольной, поэтому вы можете иметь традиционную структуру com.example.wh независимо. С этой точки зрения единственное реальное различие между модулями и библиотеками заключается в том, что модули используют API-интерфейс Play напрямую.

Во-вторых, заметка о языке. Поскольку Java и Scala изначально поддерживаются Play 2, вы можете реализовать свой модуль на любом языке. Если модуль имеет свой собственный API, который могут использовать приложения, превосходная совместимость между Java и Scala означает, что ваш выбор языка — в большинстве случаев — не зависит от того, какое приложение использует ваш API.

1. Начало работы

В качестве простого введения мы собираемся создать базовый модуль ведения журналов, который — следуя лучшим отраслевым практикам — записывает вывод в окно консоли. Этот модуль называется mylogger, потому что сегодня понедельник, и я сейчас не очень креативен. Этот модуль будет (в основном) написан на Java.

Вы можете представить себе модуль Play 2 как приложение Play 2, в котором отсутствует пара файлов. Таким образом, вы создаете модуль так же, как и приложение. Перейдите или создайте каталог, в котором вы храните свои проекты, и используйте «play new mylogger» для создания приложения. При появлении запроса выберите вариант 2, чтобы создать простое приложение Java.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
steve@hex:/tmp$ play new mylogger
       _            _
 _ __ | | __ _ _  _| |
| '_ \| |/ _' | || |_|
|  __/|_|\____|\__ (_)
|_|            |__/
 
play! 2.0, http://www.playframework.org
 
The new application will be created in /tmp/mylogger
 
What is the application name?
> mylogger
 
Which template do you want to use for this new application?
 
  1 - Create a simple Scala application
  2 - Create a simple Java application
  3 - Create an empty project
 
> 2
 
OK, application mylogger is created.
 
Have fun!

Поскольку вместе с модулем у нас будет образец приложения, мы немного изменим структуру каталогов. На данный момент это выглядит так:

1
2
3
4
5
6
7
8
mylogger
– app
– conf
– project
– public
– target
– .gitignore
– README

В каталоге mylogger создайте две новые директории, код проекта и примеры. Скопируйте все перечисленные выше файлы в каталог кода проекта. Теперь вы должны иметь

01
02
03
04
05
06
07
08
09
10
mylogger
– samples
– project-code
      – app
      – conf
      – project
      – public
      – target
      – .gitignore
      – README

Каталог conf содержит два файла — route и application.conf.

— application.conf должен присутствовать в Play для распознавания mylogger / project-code как приложения Play, поэтому мы не можем удалить его, но можем удалить все, что в нем содержится. Любая конфигурация вашего модуля должна быть добавлена ​​в application.conf «реального» приложения.
— маршруты * должны * быть удалены. Если вы этого не сделаете, он может / заменит файл маршрутов того приложения, которое его использует, и это A Bad Thing (в основном потому, что ничего не будет работать).

Когда файл application.conf очищен и маршруты удалены, введите «play» в коде проекта, чтобы запустить консоль Play.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
steve@hex:/tmp/mylogger/project-code$ play
[info] Loading project definition from /tmp/mylogger/project-code/project
[info] Set current project to mylogger (in build file://tmp/mylogger/project-code/)
       _            _
 _ __ | | __ _ _  _| |
| '_ \| |/ _' | || |_|
|  __/|_|\____|\__ (_)
|_|            |__/
 
play! 2.0, http://www.playframework.org
 
> Type "help play" or "license" for more information.
> Type "exit" or use Ctrl+D to leave this console.
 
[mylogger] $

Теперь у нас есть действующий модуль Play 2 (который, по общему признанию, ничего не делает).

Если вы используете IDE, сейчас самое подходящее время для создания проекта — однако это руководство не зависит от IDE, поэтому вы можете использовать руководство по адресу http://www.playframework.org/documentation/2.0/IDE, если хотите сделать это.

2. Добавление некоторой функциональности

Как я упоминал выше, модули Play 2 могут иметь более традиционную структуру пакетов com.example.whither, но приложение Play по умолчанию имеет традиционную структуру app / controllers, app / models и т. Д. Мы сохраним это сейчас и изменим в следующих частях этого урока.

2.1 Разрезать и сжечь

В папке приложения у нас есть следующая структура, созданная для нас командой «play new»:

1
2
3
4
5
6
app
– controllers
      – Application.java
– views
      – index.scala.html
      – main.scala.html

Для начальной итерации этого модуля нам не нужны никакие представления, поэтому вы можете удалить пакет представлений.

Вы также можете удалить Application.java, так как мы пишем это с нуля.

2.2 Добавьте некоторый код модуля

В пакете контроллеров создайте новый класс с именем MyLogger.java. Ему не нужно ничего расширять или реализовывать, и он содержит единственный метод:

01
02
03
04
05
06
07
08
09
10
11
12
package controllers;
 
/**
 * @author Steve Chaloner
 */
public class MyLogger
{
    public static void log(String message)
    {
        System.out.println("MyLogger: " + message);
    }
}

2.3 есть пиво

Вы только что написали модуль. Иди, выпей пива.

2.4 Постпивная реализация

Когда вы смотрите в свой пустой стакан, гудя от радости создания и надвигающегося ощущения общеотраслевой славы, вы можете понять, что никто не может получить доступ к вашему модулю, потому что он сидит на вашем компьютере. Вы должны опубликовать это.

3. Публикуй и будь проклят

В этом примере мы просто опубликуем ваш локальный репозиторий. В корне вашей установки Play есть каталог репозитория, и именно здесь вы сначала добавите свой модуль.

Перед публикацией всегда проверяйте, что вы запустили «clean», иначе некоторые классы / файлы, которые вы удалили из дерева исходных текстов, могут все еще существовать в скомпилированной форме и в конечном итоге оказаться в вашем файле jar модуля. Если класс соответствует классу, который есть в вашем реальном приложении, он может быть вызван вместо вашего реального класса. Который отстой.

В консоли Play используйте «clean», а затем «publish-local», чтобы упаковать свой модуль и опубликовать его в локальном репозитории:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
[mylogger] $ publish-local
[info] Updating {file:/tmp/mylogger/project-code/}mylogger...
[info] Packaging /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1-1.0-SNAPSHOT-sources.jar ...
[info] Done packaging.
[info] Wrote /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1-1.0-SNAPSHOT.pom
[info] Done updating.
[info] :: delivering :: mylogger#mylogger_2.9.1;1.0-SNAPSHOT :: 1.0-SNAPSHOT :: release :: Mon Mar 19 20:57:26 CET 2012
[info]  delivering ivy file to /tmp/mylogger/project-code/target/scala-2.9.1/ivy-1.0-SNAPSHOT.xml
[info] Compiling 1 Java source to /tmp/mylogger/project-code/target/scala-2.9.1/classes...
[info] Generating API documentation for main sources...
model contains 4 documentable templates
[info] Packaging /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1-1.0-SNAPSHOT.jar ...
[info] Done packaging.
[info] API documentation generation successful.
[info] Packaging /tmp/mylogger/project-code/target/scala-2.9.1/mylogger_2.9.1-1.0-SNAPSHOT-javadoc.jar ...
[info] Done packaging.
[info]  published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/poms/mylogger_2.9.1.pom
[info]  published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/jars/mylogger_2.9.1.jar
[info]  published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/srcs/mylogger_2.9.1-sources.jar
[info]  published mylogger_2.9.1 to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/docs/mylogger_2.9.1-javadoc.jar
[info]  published ivy to /home/steve/development/play/play-2.0/framework/../repository/local/mylogger/mylogger_2.9.1/1.0-SNAPSHOT/ivys/ivy.xml
[success] Total time: 4 s, completed Mar 19, 2012 8:57:28 PM

Если вы посмотрите в $ PLAY_HOME / repository / local, вы увидите каталог mylogger. Поскольку мы не называли название организации, она считается такой же, как и сам модуль. Зайдите в mylogger, и вы увидите артефакт — mylogger_2.9.1. Часть 2.9.1 имени файла происходит от самой Play и является (кажется,) версионирующей вещью. Если кто-то знает больше об этом, пожалуйста, прокомментируйте и дайте мне знать.

Внутри mylogger_2.9.1 у нас есть версия модуля, в данном случае 1.0-SNAPSHOT, которая, в свою очередь, содержит файлы jar, исходные файлы jar, информацию о Maven и Iyy и т. Д.

Откуда вся эта информация? Он основан на файле проекта / Build.scala. Здесь вы можете указать название модуля, организацию, версию и другую информацию. Пока что мы сохраним все как есть, но этот чрезвычайно важный файл будет обновляться по мере углубления в некоторые проблемы.

4. Предоставление образца

Вы можете написать лучший, самый невероятно полезный модуль в мире, но без примера приложения а) покажите, как оно работает, и б) покажите, КАК это работает, у вас будут проблемы с тем, чтобы убедить людей в этом. Вот почему мы изменили структуру каталогов обратно при первом создании модуля. Откройте другой терминал и перейдите в каталог mylogger / samples — самое время показать, на что способен mylogger.

4.1 Пример приложения — это приложение Play

Поскольку мы пишем модуль Play, имеет смысл предоставить приложение Play в качестве примера. Теперь мы находимся в mylogger / samples, используя «play new mylogger-sample» для создания примера приложения. Опять же, выберите вариант 2, чтобы сделать простое приложение Java.

4.2 Объявление зависимостей

Чтобы использовать mylogger, мы должны объявить зависимость для него в mylogger-sample / project / Build.scala. Откройте этот файл и измените

1
2
3
4
val appDependencies = Seq(
     // Add your project dependencies here,
   )

в

1
2
3
val appDependencies = Seq(
      "mylogger" % "mylogger_2.9.1" % "1.0-SNAPSHOT"
    )

Вы можете видеть, что это соответствует пути к хранилищу mylogger / mylogger_2.9.1 / 1.0-SNAPSHOT.

В наглом акте лени мы также объявим локальный репозиторий местом для поиска нашего модуля. + Изменить

1
2
3
val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
     // Add your own project settings here
   )

в

1
2
3
val main = PlayProject(appName, appVersion, appDependencies, mainLang = JAVA).settings(
  resolvers += "Local Play Repository" at "file://path/to/play-2.0/repository/local"
)

(но измените путь, чтобы быть правильным для вашей локальной установки)

В каталоге mylogger / samples / mylogger-sample запустите консоль Play, используя «play». Если вы используете команду «зависимости», вы увидите, что mylogger теперь является зависимостью приложения.

ВАЖНАЯ ЗАМЕТКА! Поскольку мы запустили консоль Play после изменения Build.scala, изменения были автоматически получены. Если вы изменяете этот файл, когда консоль открыта, используйте «reload», чтобы убедиться, что изменения используются.

4.2 Использование вашего модуля

В вашем новом приложении Play по умолчанию мы добавим одну строку в controllers / Application.java для вызова MyLogger:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
package controllers;
 
import play.mvc.Controller;
import play.mvc.Result;
import views.html.index;
 
public class Application extends Controller
{
    public static Result index()
    {
        MyLogger.log("Here's my log message");
        return ok(index.render("Your new application is ready."));
    }
}

Обратите внимание, что нам не нужно импортировать MyLogger, поскольку он также находится в пакете контроллеров.

«Запустите» приложение и перейдите по адресу http: // localhost: 9000. Через некоторое время страница будет отображаться, и в консоли вы увидите

1
2
[info] play - Application started (Dev)
MyLogger: Here's my log message

Перезагрузите страницу несколько раз, и вы увидите, что сообщение журнала появляется каждый раз.

5. Выпей еще пива

Поздравляю, теперь у вас есть модуль и рабочий образец. Это на самом деле не добавляет особой ценности вашему образцу приложения, но это то, что будет рассмотрено в части 2. Тем временем, зайдите в холодильник и возьмите себе еще пива.

Вы можете скачать полный исходный код для этого примера здесь

Ссылка: Написание модулей для Play 2, часть 1: Получите кое-что от нашего партнера JCG Стива Чалонера в блоге Objectify .