Как стать автором
Поиск
Написать публикацию
Обновить

Компактный Java сервлет для мобильного веб

Время на прочтение7 мин
Количество просмотров6.3K

Основная область программирования для меня, это разработка программного обеспечения для автоматизации учёта в торговли. С возможностью использовать для этого сервлеты Java я столкнулся в 2009 году, когда вместе с последней, вышедшей для десктопа, версией Openbravo POS шёл модуль ресторана для PDA. Основной идей тогда для разработчиков Openbravo POS было, чтобы не усложнять десктопную версию приложения, вынести узкую бизнес-логику в отдельное небольшое приложение, главной изюминкой которого был компактный веб-интерфейс для доступа с любого устройства, а не только того, где может быть запущена Java c Swing. При этом тогда предполагалось, что сервлет не только будет работать с одной и той-же базой, что и десктоп версия, но и контейнер для него будет интегрирован в приложение на десктопе, после запуска которого пользователь автоматический получал доступ к POS в радиусе действия Wi-Fi сети. В рамках комьюнити данная идея дальнейшего развития не получила, но я с 2012 для своих клиентов заложенными тогда принципы продолжаю пользоваться, и в данной статье расскажу читателям, как используя Stripes Framework в связке с jQuery Mobile и ORMLite, получить инструмент для быстрой разработки небольших сервлетов ориентированных на мобильный веб.

Инструментарий


Обычно, когда ищешь инструмент разработки, то стараешься найти что-то универсальное, что можно изучив однажды использовать повторно на протяжении достаточно долгого времени. В 2012 года именно с этим я столкнулся, когда попытался переделать исходный код ресторанного модуля Openbravo POS. В его основе лежал фреймворк Struts 1, изучать написание XML-схем для которого меня совсем не радовало, но на удачу, как раз в тот момент, мне на глаза попался обзор технологий экосистемы Java от RebelLabs. Один из разделов этого обзора был посвящён популярности веб-фреймворков у разработчиков, в эту 10-ку с почётными 2% входил Stripes. С его освоения я и начал изучение основ разработки Java сервлетов. Также мне помогло то, что к тому моменту на Хабре в «Песочнице» уже была обзорная статья про этот фреймворк.

В Stripes всё подчинено логике реакции на контролеры(ActionBean), которые отвечают за получение доступа к модели данных для дальнейшего отображения пользователю через шаблоны страниц JSP. Так как мне нужен был мобильный веб-интерфейс, то для визуальной части я выбрал jQuery Mobile, главный плюс которого, это возможность практически не касаясь JavaScript использовать только HTML5 разметку для построения динамической реакции на действия контролера.

Третьим элементом, отвечающим за работу с моделью данных, мной сначала был выбран совсем простой Persist ORM/DAO, но когда его функционала стало недостаточно, я сменил его на более мощный ORMLite. Главным при выборе стала лёгкость использования уже существующей модели представления и отсутствия необходимости написания SQL-запросов обходясь, как и в случае Stripes, только аннотациями.

Модель-Представление-Контролер


Ключевым в Stripes является 100% ориентированность на концепцию MVC(Model-View-Controller). А главной целью создания данного фреймворка в 2005 году было создание более легковесной реализация MVC концепции для Java EE, чем была реализована в популярном на тот момент фреймворке Struts. К версии 1.5 в 2008 году эта цель авторами Stripes была полностью достигнута и данный фреймворк начал набирать популярность среди разработчиков.

При проектировании структуры исходного кода сервлета следует стараться не выходить за рамки парадигмы Модель-Представление-Контролер, что не очень сложно сделать для большинства задач при создании CRUD-приложений. Для примера, в исходном коде для справочника товаров, это будет выглядеть так:

Источник данных, исходная SQL-таблица
CREATE TABLE PRODUCTS (
    ID VARCHAR(255) NOT NULL,
    NAME VARCHAR(255) NOT NULL,
    CODE VARCHAR(255) NOT NULL,
    PRICESELL DOUBLE NOT NULL,
    CATEGORY VARCHAR(255) NOT NULL,
    PRIMARY KEY (ID),
    CONSTRAINT PRODUCTS_FK_1 FOREIGN KEY (CATEGORY) REFERENCES CATEGORIES(ID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE UNIQUE INDEX PRODUCTS_CODE_INX ON PRODUCTS(CODE);
CREATE UNIQUE INDEX PRODUCTS_NAME_INX ON PRODUCTS(NAME);


Модель данных с аннотациями для ORMLite
@DatabaseTable(tableName = "PRODUCTS")
public class Product {

    public static final String ID = "ID";
    public static final String NAME = "NAME";
    public static final String CODE = "CODE";
    public static final String PRICESELL = "PRICESELL";
    public static final String CATEGORY = "CATEGORY";

    @DatabaseField(generatedId = true, columnName = ID)
    private UUID id;

    @DatabaseField(columnName = NAME, unique = true, canBeNull = false)
    private String name;
    
    @DatabaseField(columnName = CODE, unique = true, canBeNull = false)
    private String code;

    @DatabaseField(columnName = PRICESELL, canBeNull = false)
    private BigDecimal pricesell;

    @DatabaseField(foreign = true,
            columnName = CATEGORY,
            foreignColumnName = ProductCategory.ID,
            foreignAutoRefresh = true,
            canBeNull = false)
    private ProductCategory productCategory;

    // ...
    // Перечисления методов get и set.
    // ...
}



В начале, с помощью ORMLite, задаётся структура модели данных и её связь с реляционной базой данных(значение полей tableName и columnName). Затем через геттеры и сеттеры модель предоставляет доступ для остальных классов и методов сервлета.

Контроллер Stripes для ввода/вывода данных
public class ProductCreateActionBean extends ProductBaseActionBean {

    private static final String PRODUCT_CREATE = "/WEB-INF/jsp/product_create.jsp";

    @DefaultHandler
    public Resolution form() {
        // Открытие формы для заполнения.
        return new ForwardResolution(PRODUCT_CREATE);
    }

    public Resolution add() {
        // ...
        // После проверки полученных значений, создание записи в таблице.
        // ...
    }

    @ValidateNestedProperties({        
        @Validate(on = {"add"},
                field = "name",
                required = true,
                trim = true,
                maxlength = 255),
        @Validate(on = {"add"},
                field = "code",
                required = true,
                trim = true,
                minlength = 8,
                maxlength = 13),
        @Validate(on = {"add"},
                field = "priceSell",
                required = true,
                converter = BigDecimalTypeConverter.class),
        @Validate(field = "productCategory.id",
                required = true,
                converter = UUIDTypeConverter.class)
    })
    @Override
    public void setProduct(Product product) {
        super.setProduct(product);
    }

}


Контроллер перехватывает данные передаваемые пользователем и обрабатывает их согласно заданных аннотаций. Например, выполняя Resolution form(), получив значение ключевого поля productCategory.id, он пропускает его через UUIDTypeConverter, проверяя соответствует-ли оно допустимым для UUID критериям.

Шаблон JSP с разметкой jQueryMobile и полями Stripes

    <!-- Заглавие страницы -->

    <stripes:layout-component name="content">
        <stripes:errors />
        <stripes:messages />
        <stripes:form action="/ProductCreate.action?add">
            <div>
                <stripes:hidden name="product.productCategory.id" value="${actionBean.product.productCategory.id}"/>
            </div>
            <ul data-role="listview" data-inset="true">                
                <li class="ui-field-contain">
                    <stripes:label name="label.Product.name" for="productName" />
                    <input name="product.name" id="productName" type="text"
                           data-clear-btn="true">
                </li>
                <li class="ui-field-contain">
                    <stripes:label name="label.Product.code" for="productCode" />
                    <input name="product.code" id="productCode" type="text"
                           data-clear-btn="true">
                </li>
                <li class="ui-field-contain">
                    <stripes:label name="label.Product.price" for="productPrice"/>
                    <input name="product.priceSell" id="productPrice" type="number"
                           step="0.01"                           
                           value="0.00"
                           data-clear-btn="true">
                </li>
                <li class="ui-body ui-body-b">
                    <fieldset class="ui-grid-a">
                        <div class="ui-block-a">
                            <sdynattr:submit name="add" data-theme="a"/>
                        </div>
                        <div class="ui-block-b">
                            <sdynattr:reset name="clear" data-theme="b"/>
                        </div>
                    </fieldset>
                </li>
            </ul>        
        </stripes:form>
    </stripes:layout-component>

    <!-- Окончание страницы -->




В шаблоне страницы разметка jQuery Mobile также может служить для предварительной проверки вводимых данных, например в визуальной форме предлагая пользователю на мобильном устройстве разные клавиатуры для текста и чисел(в input параметр type равен "text" или "number").

Для чего подходит


В конце прошлого 2013 года RebelLabs был опубликован новый обзор перспектив развития фреймворков в будущем 2014 году. Stripes в данный обзор не вошёл, так как в основном внимание было уделено более полярным чем он фреймворкам, таким как Spring, Grails или Vaadin. Но мне кажется, что если совместно с ним использовать jQuery Mobile и ORMLite, то и он сейчас найдёт свою нишу в инструментарии разработчика на Java. По крайней мере в 4 из 7 предложенных RebelLabs сфер применения с ним можно чувствовать себя вполне уверенно:
  1. Приложения CRUD — об этом было выше, если всё делать последовательно и по одной схеме, то очень сложно сделать плохо. Главное при проектировании стараться каждое действие контроллера делать максимально полным, но не переполненным.
  2. Мобильные приложения — тут основная нагрузка лежит на jQuery Mobile, для Java программиста несомненный плюс, что кроме HTML5 можно не трогать JavaScript и CSS.
  3. Прототипы приложений — это основное для чего я использую эту связку, набрав с 10-ок сервлетов в портфолио, можно отдельные компоненты каждого из них легко между собой тасовать под разные бизнес-процессы.
  4. Портирование десктоп приложений — а с этого у меня всё и началось, и именно для такого применения я могу порекомендовать в первую очередь сплав этих трёх фрейморков.



Это итог, новый интерфейса с jQuery Mobile версии 1.4 в 2014 году, в сравнении с тем интерфейсом, что был в 2009 году у PDA модуля Openbravo POS.

В качестве примера практической реализации изложенного в статье, небольшой проект CRUD-сервлета для каталог товара: github.com/nordpos-mobi/product-catalog
Теги:
Хабы:
Всего голосов 8: ↑4 и ↓40
Комментарии0

Публикации

Ближайшие события