Разработка базовой функциональности сайта c Webix и Struts

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

Генераторы кода, автокомплиты, анализаторы кода, библиотеки и фреймворки прочно вошли в жизнь разработчиков. Все эти инструменты позволяют сократить время разработки сайта до минимума. Одновременно с ними развивается и сам интернет. Если раньше сайты представляли собой статическую информацию с минимальной функциональностью, то сейчас они являются полноценными приложениями, позволяющими выполнять все то, что раньше можно было сделать только на десктопе. Одним из таких инструментов для быстрого создания интерфейса веб-приложения является JavaScript библиотека Webix.

Давайте рассмотрим пример того, как можно создать сайт для анонсирования предстоящих конференций по front-end разработке, используя Webix и Java-фреймворк Struts 2.

Вот что у вас должно получится в результате выполнения всех шагов данного туториала:

сайт, сделанный с Struts и Webix

Нам необходимо разработать сайт, отображающий список предстоящих событий по front end-разработке. Кроме этого, надо реализовать возможность для добавления новых событий и докладов в каждое событие, а также возможность просмотра контактной информации.

Для реализации интерфейса будем использовать JavaScript UI библиотеку Webix, а серверную часть реализуем на Java-фреймворке Struts 2 и Hibernate с MySQL.

Для разработки будет использован IDE Eclipse. Более того, все то же самое можно повторить в любой другой IDE, предназначенной для Java. Для того чтобы Java-программа была доступна пользователям, нам необходим веб-сервер. Apache Tomcat — популярный и достаточно простой в использовании веб-сервер. Подробнее о настройке Apache Tomcat и среды разработки, можно почитать здесь.

Создание приложения и настройка Struts 2

Итак, сейчас мы создадим новое Maven-приложение с архетипом maven-archetype-webapp. Для этого в Eclipse нужно открыть File — New — Project. В появившемся окне ищем Maven Project, затем выбираем его и жмем Next.

Затем мы должны выбрать, где создать наш проект: либо в workspace, либо в другом месте. На этом этапе необходимо убедиться, что опция “Create a simple project” выключена. Далее вам необходимо выбрать в следующем окне архетип Maven-проекта. В нашем случае — это maven-archetype-webapp. Итак, выбираем и жмем Next.

Остается самое важное — выбрать название и версию проекта! В Maven каждый проект идентифицируется парой groupId/artefactId. Обычно в качестве groupId используют название организации, а artefactId — название проекта. Вот так выглядят мои настройки:

Настройки Maven project

Жмем Finish — и наше приложение создано! Давайте убедимся, правильно ли оно работает. Для этого создадим тестовый файл src/main/webapp/index.jsp со следующим содержанием:

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Проверка связи</title>
</head>
<body>
    Наше новое приложение будет здесь!
</body>
</html>

Я настоятельно рекомендую использовать кодировку UTF-8 для сайтов с кириллицей. Если же выбрана иная кодировка, то в свойствах каждого файла нужно вручную установить UTF-8.

После этого нам нужно запустить приложение. Для этого нажмите на проекте правой кнопкой, выберите Run As — Run on Server — Tomcat v7.0 at localhost (либо любой другой ваш веб-сервер) и нажмите Finish. Если все прошло успешно, то открыв в браузере путь http://localhost:8080/MyApp/ , вы сможете увидеть вот такую тестовую страничку:

<>

Возможно, в Eclipse в проекте будет подсвечена ошибка на странице index.jsp. Чтобы ее решить, надо отправиться в Build Path, кликнув правой кнопки на проекте — Build Path — Configure Build Path. В открывшемся окне переходим на вкладку Libraries и жмем Add Library. Выбираем Server Runtime — Apache Tomcat v7.0 — Finish. После этого делаем в меню Project — Clean и ждем, пока ошибка не исчезнет.

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

Java Resources:
/src/main/java — здесь хранятся все Java-классы проекта.
/src/main/resources — здесь находятся файлы конфигурации: struts.xml, log4j.xml, hibernate.cfg.xml.
Deployed Resources:
src/main/webapp — место для хранения веб-ресурсов: javascript, css, картинки, файлы представления *.jsp.
/src/main/webapp/WEB-INF/web.xml — файл-дескриптор web-проекта.
pom.xml — это файл конфигурации Maven. Здесь мы будем описывать сам проект и его зависимости.

Пришло время настроить Struts 2. Это расширяемый фреймворк для создания Java web-приложений. Struts предоставляет собой набор готовых решений для маппинга запросов, который берет на себя рутинную работу по обработке входящих запросов и формированию ответов на основе представлений.

Для начала надо добавить зависимости Struts 2 в файл pom.xml:

...
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-core</artifactId>
            <version>2.3.1.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.struts.xwork</groupId>
            <artifactId>xwork-core</artifactId>
            <version>2.3.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.struts</groupId>
            <artifactId>struts2-json-plugin</artifactId>
            <version>2.3.16</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>
    </dependencies>
    ...

После каждого изменения зависимостей рекомендуется сделать обновление зависимостей: клик правой кнопкой на проекте — Maven — Update Project — Выбрать свой проект — Ok.

Теперь у нас есть свой собственный Struts 2, который далее мы будем настраивать. Давайте откроем файл src/main/webapp/WEB-INF/web.xml и отредактируем его содержимое:

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>Archetype Created Web Application</display-name>
    <filter>
        <filter-name>struts2</filter-name>
            <filter-class>
            org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
            </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>struts2</filter-name>
        <url-pattern>*</url-pattern>
    </filter-mapping>
</web-app>

Здесь мы сообщаем серверу, что маршрутизацией запросов будет заниматься Struts 2. Благодаря этому Java-фреймворку все приходящие на сервер запросы будут отправляться в указанный класс, и уже он будет решать, что с ними дальше делать.

Теперь пора заняться настройкой библиотеки логирования log4j. Для этого создайте файл src/main/resources/log4j.xml со следующим содержанием:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration PUBLIC "-//log4j/log4j Configuration//EN" "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
       <layout class="org.apache.log4j.PatternLayout">
          <param name="ConversionPattern" value="%d %-5p %c.%M:%L - %m%n"/>
       </layout>
    </appender>
    <logger name="com.opensymphony">
        <level value="DEBUG" />
    </logger>
    <logger name="org.apache.struts2">
         <level value="DEBUG" />
    </logger>
     <root>
        <priority value="INFO"/>
        <appender-ref ref="STDOUT" />
     </root>    
</log4j:configuration>

Все готово для непосредственной настройки Struts 2 и маршрутизации. Создадим файл src/main/resources/struts.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
   "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
   "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
    <constant name="struts.devMode" value="true" />
    <package name="defaultpages" namespace="/" extends="struts-default">
        <action name="index">
            <result>/index.jsp</result>
        </action>
    </package>
</struts>

В этом файле производится настройка маршрутизации запросов. В нашем случае мы указали, что запрос http://localhost:8080/MyApp/index или http://localhost:8080/MyApp/ получит в ответ содержимое файла index.jsp. Файл index.jsp называется представлением и содержит html-код страницы.

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

Запускаем сервер и открываем в браузере страницу http://localhost:8080/MyApp/index.action. Если вы видите то же, что и я — значит, что у вас все получается!

test page web app

Разработка основных страниц и навигации между ними

Struts 2 настроен и готов к использованию, поэтому пришло время заняться разработкой front-end части приложения. На клиентской стороне для реализации интерфейса будем использовать библиотеку UI-элементов Webix. Она представляет собой библиотеку для быстрого создания интерфейса на основе готовых компонентов.

Webix очень прост в изучении. Для начала отправимся на сайт Webix и скачаем последнюю версию библиотеки. Затем распакуем архив и скопируем директорию codebase в папку src/main/webapp/. После этого стоит обновить проект: File — Refresh в Eclipse, чтобы веб-сервер увидел новые файлы.

Подключаем Webix на страницу index.jsp:

<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Проверка связи</title>
    <link rel="stylesheet" href="./codebase/webix.css" type="text/css" media="screen" charset="utf-8">
    <script src="./codebase/webix.js" type="text/javascript" charset="utf-8"></script>
</head>

Webix использует древовидный объект для описания необходимого интерфейса. Каждый элемент в нем называется view. В зависимости от типа view, каждый элемент будет иметь свои особенности. Популярными типами в Webix являются toolbar, button, window, list, datatable. Полный список всех view можно посмотреть здесь.

Отдельно стоит отметить view: ‘layout’ (лэйаут). Во-первых, это свойство у лэйаута часто опускают, потому что распознать лэйаут всегда можно по свойствам rows/cols. Каждый лэйаут представляет собой либо строку, либо столбец из нескольких отдельных ячеек. Используя вложенные лэйауты, можно построить лэйаут любого типа и конфигурации.

Например:

webix.ui({
    container:"layout_div",
    rows:[
        {template:"row 1"},
        {template:"row 2"},
        { cols:[
         { template:"col 1" },
         { template:"col 2" },
         { template:"col 3" }
        ]}
    ]
});

Webix layout

Webix Layout позволяет легко указывать размеры в пикселях, при этом остальные размеры рассчитываются самостоятельно. Для сайта с фиксированной шириной контента и полями слева и справа можно использовать следующую конструкцию:

webix.ui({
        container:"myapp",
        cols: [{}, {
            width: 1280,
            template: "Здесь ваш сайт"
        }, {}]
    });

В таком случае ширина центрального контейнера составит 1280 пикселей, а ширина полей рассчитается автоматически. Подробнее про использование компонента layout можно почитать в документации.

Общие для всех страниц JavaScript-функции и CSS-стили будем хранить в файлах src/main/webapp/codebase/myapp.js и src/main/webapp/codebase/myapp.css. Для этого создадим эти файлы и в myapp.css добавим правило:

html, body {
    width: 100%;
    height: 100%;
    margin: 0px;
    padding: 0px;
    overflow-x: hidden;
    background-color: #580B1C;
}
#myapp {
    width: 100%;
    height: 100%;
}

Наш сайт должен содержать такие такие привычные элементы, как шапка с логотипом, главным меню и фотографиями, нижняя часть с ссылками и центральная часть с контентом. Для этого внесем изменения в файл index.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Webix - Front-End события</title>
    <link rel="shortcut icon" href="favicon.ico" />



    <link rel="stylesheet" href="./codebase/webix.css" type="text/css" media="screen" charset="utf-8">
    <link rel="stylesheet" href="./codebase/myapp.css" type="text/css" media="screen" charset="utf-8">
    <script src="./codebase/webix.js" type="text/javascript" charset="utf-8"></script>
    <script src="./codebase/myapp.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
    <div id='myapp'></div>
    <script type="text/javascript" charset="utf-8">
    webix.ui({
        container:"myapp",
        cols: [{}, {
            width: 1280,
            rows: [
                { template: "header", height: 250 },
                { template: "content"},
                { template: "content", height: 30 }
            ]
        }, {}]
    });
    </script>
</body>
</html>

Чтобы добавить сайту индивидуальности поменяем цвет и стиль сайта. К счастью, разработчики Webix создали инструмент Skin Builder, с помощью которого можно быстро и легко выбрать понравившийся стиль, поменять цвета, шрифты и скачать новый стиль. Я буду использовать цвет #74182C. Если вы хотите использовать такой же цвет, то можете воспользоваться ссылкой на мой настроенный стиль: //webix.com/skin-builder/78aa39e4.

webix skin builder

Скачайте свой стиль, распакуйте его и файлы webix.css, webix.js, а затем переместите все эти файлы в папку src/main/webapp/codebase, заменив существующие. После этого не забудьте обновить проект в Eclipse.

Теперь создадим шапку сайта. Для этого расширим конфигурацию webix в файле index.jsp:

...
<div id='myapp'></div>
<div id="header" style="display: none;">
    <div class="confname">Front-End<br>Events</div>
    <div class="confdsc">Все события в области web-разработки здесь!</div>
</div>
<script type="text/javascript" charset="utf-8">
    var imgTemplate = function(obj){
        return '<img src="'+obj.src+'" class="content" ondragstart="return false"/>'
    };

    webix.ui({
        container:"myapp",
        cols: [{}, {
            width: 1280,
            rows: [
                {
                    height: 250,
                    borderless:true,
                    cols: [{
                        rows: [
                            { view: "template", template: "html->header", css: "header", borderless: true},
                            { cols: [
                                {},
                                { view:"toolbar", height: 40, borderless:true, cols:[
                                    {view:"segmented", multiview:false, value:1, width: 600, options:[
                                        { id:"upcoming", value:"Предстоящие события" },
                                        { id:"contacts", value:"Контакты" }
                                    ], on: {
                                        'onChange': function(newValue, oldValue){
                                            window.location.href = newValue;
                                        }
                                    }, value:"upcoming" }
                                ]},
                            {}
                        ]}
                    ]},
                    { rows: [
                        { height: 10},
                        {
                            view:"carousel",
                            id:"carousel",
                            width:410,
                            height: 230,
                            borderless: true,
                            cols:[
                                { css: "image", template:imgTemplate, data:{src:"photos/photo1.jpg"} },
                                { css: "image", template:imgTemplate, data:{src:"photos/photo2.jpg"} },
                                { css: "image", template:imgTemplate, data:{src:"photos/photo3.jpg"} },
                                { css: "image", template:imgTemplate, data:{src:"photos/photo4.jpg"} },
                                { css: "image", template:imgTemplate, data:{src:"photos/photo5.jpg"} },
                                { css: "image", template:imgTemplate, data:{src:"photos/photo6.jpg"} }
                            ]
                        },
                    {}
                ]}
            ]
        },
        { template: "content"},
        { template: "footer", height: 30 }
    ]
}, {}]
});

</script>
</body>
</html>

Здесь мы разбили верхнюю ячейку на две колонки. В левой будем отображать логотип и меню, а в правой — фотографии с мероприятий. Для меню будет использован элемент toolbar с кнопкой segmented. Для фотографий — carousel с фотографиями. Фотографии надо предварительно обрезать до размера 400*220 и сохранить в папке src/main/webapp/photos/.

Также в коде выше мы добавили главное меню с помощью кнопки segmented. Чтобы осуществлять переход между страницами, на элемент (кнопку типа segmented) мы повесили событие onChange, которое будет возникать, в случае если пользователь изменит выделенное значение. Если это произойдет — нам нужно будет перейти на выбранную страницу:

    'onChange': function(newValue, oldValue){
        window.location.href = newValue;
    }

Также добавим немного CSS-кода в файл myapp.css:

.header {
    padding: 10px;
    box-sizing: border-box;
    background-color: #580B1C;
    color: #ffffff;
}
.confname {
    font-size: 62px;
    float: left;
    width: 450px;
}
.confdsc {
    font-size: 13px;
    margin: 10px 0px;
    width: 800px;
    float: left;
}

Запускаем сервер, открываем в браузере страницу http://localhost:8080/MyApp/index.action. Если вы видете что-то подобное на скриншот ниже, то значит, что вы сделано правильно!

Страница сайта Struts и WebixA

Теперь добавим нижнюю часть сайта. Для этого в файле index.jsp заменим конфигурацию { template: «footer», height: 30 } на следующий код:

  {
        height: 30,
        paddingY: 6,
        cols: [
            {},
            {
                template: "html->footer",
                css: "footer",
                borderless: true,
                width: 160
            }, {
        }]
    }

Добавим в index.jsp html-контейнер с кодом для нижней части сайта:

<div id="footer" style="display: none;">
    <ul>
        <li><a href="upcoming">Главная</a></li>
        <li><a href="contacts">Контакты</a></li>
    </ul>
</div>

В файл myapp.css добавляем код для оформления этой части сайта:

.footer {
    background-color: #580B1C;
    color: #ffffff;
}
.footer ul {
    margin: 3px;
    padding: 0px
}
.footer ul li {
    display: inline;
    padding-right: 14px;
    list-style-type: none;
}
.footer ul li a {
    color: #ffffff;
    text-decoration: none;
}
.footer ul li a:hover {
    text-decoration: underline;
}

Запускаем сервер, открываем в браузере http://localhost:8080/MyApp/index.action. Теперь у нас на сайте есть все необходимое, за исключением контента.

сайт, сделанный с Struts и  Webix

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

html-код хидера и футера вынесем в соответствующие файлы:

src/main/webapp/header.jsp:

<%@ page contentType="text/html; charset=UTF-8" %>
    <div id="header" style="display: none;">
        <div class="confname">Front-End<br>Events</div>
        <div class="confdsc">Все события в области web-разработки здесь!</div>
    </div>

src/main/webapp/footer.jsp:

<%@ page contentType="text/html; charset=UTF-8" %>
    <div id="footer" style="display: none;">
        <ul>
            <li><a href="upcoming">Главная</a></li>
            <li><a href="contacts">Контакты</a></li>
        </ul>
   </div>

— в файле myapp.js добавим функции, которые возвращают конфигурацию для нижней части сайта, фото-галереи и главного меню:

src/main/webapp/codebase/myapp.js:

function getTopMenu(selectedValue) {
    return { cols: [{}, { view:"toolbar", height: 40, borderless:true, cols:[
        {view:"segmented", multiview:false, value:1, width: 600, options:[
           { id:"upcoming", value:"Предстоящие события" },
           { id:"contacts", value:"Контакты" }
        ], on: {
            'onChange': function(newValue, oldValue){
                window.location.href = newValue;
            }
        }, value: selectedValue }
    ]}, {}] };
}

function getFooter() {
    return {
        height: 30,
        paddingY: 6,
        cols: [
            {},
            {
                template: "html->footer",
                css: "footer",
                borderless: true,
                width: 160
            },
            {}
        ]
    };
}

function getPhotos() {
    var imgTemplate = function(obj){
        return '<img src="'+obj.src+'" class="content" ondragstart="return false"/>'
    };
    return { rows: [
 { height: 10},
        {
            view:"carousel",
            id:"carousel",
            width:410,
            height: 230,
            borderless: true,
            cols:[
                { css:"image", template:imgTemplate, data:{src:"photos/photo1.jpg"}},
                { css:"image", template:imgTemplate, data:{src:"photos/photo2.jpg"}},
                { css:"image", template:imgTemplate, data:{src:"photos/photo3.jpg"}},
                { css:"image", template:imgTemplate, data:{src:"photos/photo4.jpg"}},
                { css:"image", template:imgTemplate, data:{src:"photos/photo5.jpg"}},
                { css:"image", template:imgTemplate, data:{src:"photos/photo6.jpg"}}
            ]
        },
        {}
    ]};
}

Теперь страница index.jsp может быть преобразована к следующему виду:

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Webix - Front-End события</title>
    <link rel="shortcut icon" href="favicon.ico" />
    <link rel="stylesheet" href="./codebase/webix.css" type="text/css" media="screen" charset="utf-8">
    <link rel="stylesheet" href="./codebase/myapp.css" type="text/css" media="screen" charset="utf-8">
    <script src="./codebase/webix.js" type="text/javascript" charset="utf-8"></script>
    <script src="./codebase/myapp.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
    <jsp:include page="header.jsp" />
    <jsp:include page="footer.jsp" />
    <div id='myapp'></div>

    <script type="text/javascript" charset="utf-8">
        webix.ui({
            container:"myapp",
            cols: [{}, {
                width: 1280,
                rows: [
                    {
                        height: 250,
                        borderless:true,
                        cols: [{
                            rows: [
                                { view: "template", template: "html->header", css: "header", borderless: true},
                                getTopMenu("upcoming")
                            ]},
                            getPhotos()
                        ]
                    },
                    { template: "content"},
                    getFooter()
                ]
            }, {}]
        });
    </script>
</body>
</html>

Итак, за небольшой промежуток времени мы сумели создать сайт с удобной навигацией благодаря использованию Webix и Java-фреймворка Struts 2. На страницах был добавлен футер, хэдер, фотогалерея и главное меню. Для создания уникального стиля сайта был использовайн онлайн инструмент Webix Skin Builder.

Скачать пакет с готовым проектом.

Теперь у нас есть сайт, осталось заполнить его контентом. Как это сделать вы узнаете во второй части туториала.

Хочется отметить, что Webix легко поддается изменениям, хорошо интегрируется с другими библиотеками и разнообразными технологиями. При работе с данной библиотекой у пользователей появляется широкий простор для действий.