Grabduck

"Правильные" прототипы. Путь Ninja.

:

Весь код можно посмотреть и скачать на GitHub

Основная идея Ninja framework это сразу приступать к работе, а не сидеть и настраивать проект. Часто прототипы это сделанные на скорую руку поделки для демонстрации и чаще всего сами прототипы не развиваются дальше, а пишется все по новой. Ну или если прототип изначально делался “правильно” и в нем все настроено (cache, i18n, миграция баз, конфиги приложения) он скорее всего будет дорабатываться в дальнейшем, но на него потребуется больше времени для разработки. На такую разработку обычно нет времени и все лепится на скорую руку, жестко забивают настройки приложения в код. Ninja как раз помогает пройти этап настройки и сразу приступить к разработке. Хотя я сам не люблю всякие комбайны, которые ограничивают тебя в выборе, но в данном случае, лично мне понравилось.

Документация
Документации там немного и как говорится - все по делу. Со всей докой можно за день ознакомится.

Лучше всего посмотреть на практике это.
Создаем Maven проект из архетипа mvn archetype:generate -DarchetypeGroupId=org.ninjaframework -DarchetypeArtifactId=ninja-servlet-jpa-blog-archetype
Не обязательно с него, просто полезно посмотреть как и что работает. я по удалял все сущности не нужные, их там пару штук.
Ну вот собственно и все, можно начинать разрабатывать) Мы получили кучу всяких зависимостей для разработки, например: jetty, freemarker, sl4j, ehcache, guice, flyway, h2 base, hibernate и др.

Для запуска приложения можно воспользоватся классом с main методом (**ninja.standalone.NinjaJetty**) ну или варку собирать.

Из приятного. Есть несколько оберток, которыми удобно пользоваться, заинжектим их в контроллер. Logger не является оберткой, но он тоже есть, настроен и им можно пользоваться.

@Inject
private Logger logger;

@Inject
private NinjaProperties ninjaProperties;

@Inject
private NinjaCache ninjaCache;

@Inject
private Messages messages;

Results (Result)

Удобная штука для веб приложений. Это билдер ответов. Собственно, что в нем есть.
У этого объекта есть несколько классов для создания Result. Они там разные, например:
Results.json() или Results.html().
Разобраться в нем просто, все понятно по названиям методов. В объект Result можно добавлять свои объекты, которые будут использоватmся в шаблонах (для генерации ответа).

Results.html().render("nameObj", object);

Шаблон можно указать самому
Results.html()
           .render("nameObj", object)
           .template("path/template.ftl.html")

или положить и назвать его в соответствии с соглашениями. Например в views/ApplicationController/index.ftl.html. Этот шаблон будет использоваться для метода index из контроллера ApplicationController.

Cache

Докумнетация
Для работы с кешом используется обертка NinjaCache. По-умолчанию используется реализация Ehcache, но так же можно использовать memcached. Для этого в конфиг (*application.conf*) надо прописать пару параметров:

cache.implementation=ninja.cache.CacheMemcachedImpl
memcached.host=127.0.0.1:11211
// user and password are optional
memcached.user=USER          
memcached.password=PASSWORD
java
Единственно memcached (в отличие от Ehcache) требует, чтобы объекты хранимые в кеше имплементили интерфейс Serializable. Посмотрим, как работать с оберткой. Тут все просто. Добавим в контроллер метод для теста.
...

private static String CACHE_KEY = "test_cache";

...

public Result testCache() {
        String test = (String) ninjaCache.get(CACHE_KEY);
        if(test == null){
           test = "new_object";
            ninjaCache.set(CACHE_KEY, test, "1d");
        }else{
            test += "_from_cache";
        }
        return Results.html();

Так же нужно прописать в Routes связь на тот метод:
@Override
    public void init(Router router) {  
     ...
     router.GET().route("/cache").with(ApplicationController.class, "testCache"); 
}

И шаблон для этой страницы (*testCache.ftl.html*).
<#import "../layout/defaultLayout.ftl.html" as layout> 
<@layout.myLayout "Test cache">    

    ${cacheObj}

<[email protected]>

при изменения в шаблонах изменения сами подхватятся, просто перегрузить страницу достаточно

Собственно при обращении к http://localhost:8080/cache сначала создастся новый объект и он сохранится в кэше, при последующих запросах, он будет браться из кэша. Так же в методе добавления объекта в кэш, можно указать время хранения (по-умолчанию 1 месяц). Если объект уже там есть с таким ключом, то он заменится.

Configuration

Документация
Все свойства приложения лежат в файле application.conf. Есть стандартные свойства ninja и можно добавлять свои.
Добавим в application.conf строку

test.prop=Hello, world!

В контроллере возьмем это свойство и добавим в ответ
...
.render("prop", ninjaProperties.get("test.prop"))
java
В шаблоне index.ftl.html, просто выведем его
...
${prop}
...

открываем http://localhost:8080 и видим содеhжимое свойства.
Так же в конфиг файле можно указать для какого окружения это значение свойства. Если в конфиг файл добавить свойство test.prop с префиксом
...
%prod.test.prop=Hello, prod!
...

и запустить приложение с ключом -Dninja.mode=prod, то на странице отобразится именно это значение. Но если кто-то любит держать настройки прода отдельно или нужно предоставить возможность эксплуатации менять их, то можно запускать приложение с ключом -Dninja.external.configuration=conf/production.conf. Все свойства с теми же ключами в приложении будут заменены на значения из этого файла.

i18n

Документация
Еще одна полезная штука, о которой следует позаботится в начале пути.
Добавим тестовое сообщение в messages.properties.

...
test=Тест
...

В шаблоне к нему можно обратится так:
...
${i18n("test")}
...

В приложении:
...
messages.get("test", Optional.of("en")).get()
...

Если файла для такой локали не найдено, то берется та, что по умолчанию.