Введение в ActiveWeb

Введение в ActiveWeb

1. обзор

В этой статье мы собираемся проиллюстрироватьActiveweb - веб-фреймворк с полным стеком от JavaLite, предоставляющий все необходимое для разработки динамических веб-приложений или веб-сервисов, поддерживающих REST.

2. Основные концепции и принципы

Activeweb использует «соглашение, а не конфигурацию» - это означает, что он настраивается, но имеет разумные значения по умолчанию и не требует дополнительной настройки. Нам просто нужно следовать нескольким предопределенным соглашениям, таким как присвоение имен классам, методам и полям в определенном предопределенном формате.

Это также упрощает разработку путем перекомпиляции и перезагрузки исходного кода в работающий контейнер (Jetty по умолчанию).

Для управления зависимостями он использует Google Guice в качестве платформы DI; чтобы узнать больше о Guice, взгляните на нашguide here.

3. Maven Setup

Для начала давайте сначала добавим необходимые зависимости:


    org.javalite
    activeweb
    1.15

Последнюю версию можно найтиhere.

Кроме того, для тестирования приложения нам понадобится зависимостьactiveweb-testing:


    org.javalite
    activeweb-testing
    1.15
    test

Проверьте последнюю версиюhere.

4. Структура приложения

Как мы уже обсуждали, структура приложения должна соответствовать определенному соглашению; вот как это выглядит для типичного приложения MVC:

image

Как мы видим,controllers,service,config иmodels должны находиться в собственном субпакете в пакетеapp.

Представления должны быть расположены в каталогеWEB-INF/views, каждый из которых имеет собственный подкаталог на основе имени контроллера. Например,app.controllers.ArticleController должен иметь подкаталогarticle/, содержащий все файлы представления для этого контроллера.

Дескриптор развертывания илиweb.xml обычно должен содержать<filter> и соответствующий<filter-mapping>.. Поскольку структура представляет собой фильтр сервлета, вместо конфигурации<servlet> существует конфигурация фильтра:

...

    dispatcher
    org.javalite.activeweb.RequestDispatcher
...

...

Нам также нужен<init-param>root_controller для определения контроллера по умолчанию для приложения - аналогично контроллеруhome:

...

    root_controller
    home

...

5. Контроллеры

Контроллеры - это основные компоненты приложения ActiveWeb; и, как упоминалось ранее, все контроллеры должны быть расположены внутри пакетаapp.controllers:

public class ArticleController extends AppController {
    // ...
}

Обратите внимание, что контроллер расширяетorg.javalite.activeweb.AppController.

5.1. Сопоставление URL-адресов контроллера

Контроллеры автоматически сопоставляются с URL-адресом в соответствии с соглашением. Например,ArticleController будет отображаться в:

http://host:port/contextroot/article

Теперь это будет сопоставлено с действием по умолчанию в контроллере. Действия - это не что иное, как методы внутри контроллера. Назовите метод по умолчанию какindex():

public class ArticleController extends AppController {
    // ...
    public void index() {
        render("articles");
    }
    // ...
}

Для других методов или действий добавьте имя метода в URL:

public class ArticleController extends AppController {
    // ...

    public void search() {
        render("search");
    }
}

URL:

http://host:port/contextroot/article/search

Мы даже можем иметь действия контроллера, основанные на методах HTTP. Просто аннотируйте метод одним из@POST, @PUT, @DELETE, @GET, @HEAD.. Если мы не аннотируем действие, по умолчанию оно считается GET.

5.2. Разрешение URL-адреса контроллера

Каркас использует имя контроллера и имя подпакета для генерации URL контроллера. Напримерapp.controllers.ArticleController.java URL:

http://host:port/contextroot/article

Если контроллер находится внутри подпакета, URL просто становится:

http://host:port/contextroot/example/article

Для имени контроллера, содержащего более одного слова (например,app.controllers.PublishedArticleController.java), URL-адрес будет разделен подчеркиванием:

http://host:port/contextroot/published_article

5.3. Получение параметров запроса

Внутри контроллера мы получаем доступ к параметрам запроса с помощью методовparam() илиparams() изAppController class.. Первый метод принимает аргумент String - имя параметра для получения:

public void search() {

    String keyword = param("key");
    view("search",articleService.search(keyword));

}

И мы можем использовать позже, чтобы получить все параметры, если нам нужно:

public void search() {

    Map criterion = params();
    // ...
}

6. Просмотры

В терминологии ActiveWeb представления часто называют шаблонами; это главным образом потому, что он использует механизм шаблонов ApacheFreeMarker вместо JSP. Вы можете узнать больше о FreeMarkerin our guide, here.

Поместите шаблоны в каталогWEB-INF/views. Каждый контроллер должен иметь подкаталог по имени, содержащий все необходимые ему шаблоны.

6.1. Отображение представления контроллера

При попадании в контроллер запускается действие по умолчаниюindex(), и фреймворк выбирает шаблонWEB-INF/views/article/index.ftl из каталога представлений для этого контроллера. Аналогично, для любого другого действия представление будет выбираться на основе имени действия.

Это не всегда то, что нам хотелось бы. Иногда мы можем захотеть вернуть некоторые представления, основанные на внутренней бизнес-логике. В этом сценарииwe can control the process with the render() method из родительского классаorg.javalite.activeweb.AppController:

public void index() {
    render("articles");
}

Обратите внимание, что расположение пользовательских представлений также должно быть в том же каталоге представлений для этого контроллера. Если это не так, добавьте к имени шаблона имя каталога, в котором он находится, и передайте его методуrender():

render("/common/error");

6.3. Просмотры с данными

Для отправки данных в представленияorg.javalite.activeweb.AppController предоставляет методview():

view("articles", articleService.getArticles());

Это занимает два параметра. Во-первых, имя объекта, используемое для доступа к объекту в шаблоне, а во-вторых, объект, содержащий данные.

Мы также можем использовать методassign() для передачи данных в представления. Нет абсолютно никакой разницы между методами view () иassign() - мы можем выбрать любой из них:

assign("article", articleService.search(keyword));

Давайте сопоставим данные в шаблоне:

<@content for="title">Articles
...
<#list articles as article>
    
        ${article.title}
        ${article.author}
        ${article.words}
        ${article.date}
    

7. Управление зависимостями

Для управления объектами и экземплярами ActiveWeb использует Google Guice в качестве основы управления зависимостями.

Допустим, нам нужен класс обслуживания в нашем приложении; это отделит бизнес-логику от контроллеров.

Давайте сначала создадим служебный интерфейс:

public interface ArticleService {

    List
getArticles(); Article search(String keyword); }

И реализация:

public class ArticleServiceImpl implements ArticleService {

    public List
getArticles() { return fetchArticles(); } public Article search(String keyword) { Article ar = new Article(); ar.set("title", "Article with "+keyword); ar.set("author", "example"); ar.set("words", "1250"); ar.setDate("date", Instant.now()); return ar; } }

Теперь давайте свяжем эту службу как модуль Guice:

public class ArticleServiceModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(ArticleService.class).to(ArticleServiceImpl.class)
          .asEagerSingleton();
    }
}

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

public class AppBootstrap extends Bootstrap {

    public void init(AppContext context) {
    }

    public Injector getInjector() {
        return Guice.createInjector(new ArticleServiceModule());
    }
}

Обратите внимание, что это имя класса конфигурации должно бытьAppBootstrap, и оно должно находиться в пакетеapp.config.

Наконец, вот как мы вводим его в контроллер:

@Inject
private ArticleService articleService;

8. тестирование

Модульные тесты для приложения ActiveWeb написаны с использованием библиотекиJSpec от JavaLite.

Мы будем использовать классorg.javalite.activeweb.ControllerSpec из JSpec для тестирования нашего контроллера и назовем тестовые классы, следуя аналогичному соглашению:

public class ArticleControllerSpec extends ControllerSpec {
    // ...
}

Обратите внимание, что имя похоже на контроллер, который он тестирует с «Spec» в конце.

Вот тестовый пример:

@Test
public void whenReturnedArticlesThenCorrect() {
    request().get("index");
    a(responseContent())
      .shouldContain("Introduction to Mule");
}

Обратите внимание, что методrequest() имитирует вызов контроллера, а соответствующий HTTP-методget(), принимает имя действия в качестве аргумента.

Мы также можем передать параметры контроллеру с помощью методаparams():

@Test
public void givenKeywordWhenFoundArticleThenCorrect() {
    request().param("key", "Java").get("search");
    a(responseContent())
      .shouldContain("Article with Java");
}

Чтобы передать несколько параметров, мы также можем связать метод с помощью этого свободного API.

9. Развертывание приложения

Приложение можно развернуть в любом контейнере сервлетов, таком как Tomcat, WildFly или Jetty. Конечно, самый простой способ развертывания и тестирования - использовать плагин Maven Jetty:

...

    org.eclipse.jetty
    jetty-maven-plugin
    9.4.8.v20171121
    
        manual
        10000
    

...

Последняя версия плагинаhere.

Теперь, наконец, мы можем запустить это:

mvn jetty:run

10. Заключение

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

Пожалуйста, обратитесь к официальномуdocumentation для получения более подробной информации.

И, как всегда, доступен пример кода, использованный в статьеover on GitHub.