The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

Создание современных web-приложений при помощи Google Web Toolkit (web javascript gui java)


<< Предыдущая ИНДЕКС Исправить src / Печать Следующая >>
Ключевые слова: web, javascript, gui, java,  (найти похожие документы)
From: Кирилл Сухов Date: Mon, 16 Apr 2010 17:02:14 +0000 (UTC) Subject: Создание современных web-приложений при помощи Google Web Toolkit Материал предоставлен редакцией журнала Системный администратор. Опубликовано в журнале "Системный администратор" N 1 2010 Любое интернет-приложение эпохи WEB2 - это прежде всего "богатый" и функциональный пользовательский интерфейс, выполненный с использованием технологии Ajax, а следовательно, JavaScript Его создание - довольно непростая, требующая скрупулезности задача, на решение которой тратишь немало времени - на отладку, обеспечение кроссбраузерной совместимости, борьбу с капризами JavaScript и прочие вещи, мало имеющие общего с разработкой и проектированием реализации бизнес-логики. К счастью, уже создано немало инструментов, облегчающих эту задачу. Фрэймворк Google Web Toolkit пусть и не единственная предназначенная для этого среда, но она уже успела себя зарекомендовать полнофункциональными, работоспособными RIA-приложениями. Что это? Зачем? На первый вопрос ответить легко - это фрэймворк-среда, набор средств и API-интерфейсов для разработки веб-приложений. Её отличительная особенность в том, что вся разработка и, что существенно, отладка ведётся на Java с помощью привычной IDE (сейчас существуют плагины для Eclipce и NetBeans) с последующей компиляцией готового приложения в HTML/JavaScript. Собственно, реальность использования сред разработки частично является ответом на второй вопрос. Создавать сложное веб-приложение на строго типизированном ООП-языке, с возможностью нормального проектирования в любимой IDE, "человеческой" отладкой, Unit тестированием ещё недавно казалось недостижимой мечтой. Google Web Toolkit во многом является воплощением этой мечты в жизнь. Процесс отладки приложения здесь гораздо более лёгок и эффективен, так как наиболее распространённые ошибки в JavaScript теперь всплывают во время компиляции, а не выполнения, а такие ошибки, как несоответствие типов или отсутствие необходимых методов, выявляются ещё на стадии написания кода. Подсказки и автодополнение - нормальный функционал IDE, хоть и не жизненно важный, но довольно существенно повышающий производительность, а полноценный рефакторинг (который также теперь доступен) в современных условиях просто необходим. Отдельно следует упомянуть про ООП-разработку. Реализация этой концепции в JavaScript вызывает много справедливых нареканий и является причиной неоправданной сложности разработки. В среде GWT вы программируете на Java, и никаких проблем такого рода не возникает. Кроме того, при написании веб-приложений теперь можно использовать такие привычные утилиты, как Jprofiler или Junit. Как это работает? Код пишется и отлаживается на Java с использованием типов данных из пакетов java.lang и java.util, а также с новыми классами, предоставляемыми GWT. Поддерживаются все внутренние типы Java (в том числе и Object). Поддерживается работа с исключениями, в том числе и определяемыми пользователем. После отладки приложения при помощи GWT-компилятора создаётся приложение, использующее традиционные веб-технологии - HTML/JavaScript/XML/JSON, которое для GWT-приложения является аналогом бинарного представления в Java. Но GWT это не совсем Java! Прежде всего не поддерживается Reflection и динамическая загрузка классов (что естественно, этот механизм просто невозможно перенести в JavaScript). Не поддерживается сериализация. Не поддерживается модификатор Strict Floating Point.(strictfp), предписывающий "строгую" арифметику для чисел с плавающей точкой. Нет финализации объекта перед сборкой мусора. GWT-приложение как любое веб-приложение состоит из клиентской (обрабатываемой в браузере) и серверной частей. Весь код, отвечающий за клиентский функционал, в процессе компиляции переводится в html/javascript и, следовательно, имеет ряд естественных ограничений. Серверная часть приложения может вызываться клиентским кодом посредством асинхронных RPC-запросов. При этом серверный код выполняется отдельно от клиентского и не имеет каких-либо ограничений, накладываемых компиляцией в JavaScript. Более того, нет ограничений в выборе технологий реализации серверной части программы. Наряду с Java это может быть PHP, Perl, Python и т.д. Механизм отложенного связывания (deffered binding), выполняемого при генерации JavaScript, обеспечивает решение проблем с кроссбраузерной совместимостью и локализацией приложения. GWT компилирует различные версии приложения под каждый браузер и локализацию. Во время запуска клиентской части такого приложения в браузере определяется нужная версия, она и поставляется пользователю. Библиотеки GWT лицензированы под Apache License 2.0, что даёт полную свободу использования среды как в открытых, так и в пропроетарных приложениях. Как установить? На компьютере должна быть установлена Java SDK версии 1.5 или выше. Ещё одно требование - наличие Apache Ant, java-утилиты для автоматизации процесса сборки. Если её нет, просто скачайте из сайта проекта (http://ant.apache.org) и распакуйте в любое удобное место, не забыв прописать переменную окружения ANT_HOME и путь к Ant/bin в переменной PATH. (Впрочем, при использовании Windows можно прибегнуть к сценарию установки в составе дистрибутива.) Сначала скачиваем дистрибутив с сайта code.google.com (http://code.google.com/intl/ru/webtoolkit/download.html) и распаковываем его в выбранную директорию. Собственно, на этом процесс установки закончен. Осталось только прописать путь к этой папке в системной переменной PATH. Для проверки работоспособности GWK перейдём в папку /samples, расположенную в корневой папке установленного фрэймворка. Это примеры простейших приложений использования среды. Заходим (в консоли) в /samples/Hello и выполняем команду: ant hosted Если всё правильно установлено, результат должен быть похож на рис. 1. Этой командой мы запускаем приложение в так называемом размещённом (hosted) режиме. В нём оно выполняется на виртуальной машине Java (JVM). Этот режим предназначен для отладки и разработки. Мы видим два окна встроенного браузера, в первом из них запущено само приложение, во втором отображается отладочная информация, в том числе данные Http-запросов. Теперь откомпилируем наше приложение в HTML/Java Script. Для этого вызовем команду: ant build запускающую GWT-компилятор. Результат его работы можно увидеть в папке samples/Hello/war, раскрыв в браузере файл MailBoxes.html. Как видим (см. рис. 2), всё прошло успешно. Правда, не впечатляет. Чтобы увидеть настоящее GWT-приложение, заглянем в папку samples/Mail, где хранятся демонстрационные примеры приложений, проведем аналогичные действия. В результате получим уже нечто вполне приемлемое (см. рис. 3). Первое приложение Теперь попробуем создать собственное простенькое GWT-приложение. Для этого воспользуемся утилитой webApp Creator, входящей в комплект GWT: webAppCreator -out MailBoxes com.samag.MailBoxes MailBoxes - это название нашего приложения (да-да, интерфейс к почтовому серверу). После выполнения команды будет создано несколько папок и файлов в папке MailBoxes/, которые составят скелет приложения и обеспечат базовый "Hello GWT" функционал: Created directory MailBoxes/src Created directory MailBoxes/war Created directory MailBoxes/war/WEB-INF Created directory MailBoxes/war/WEB-INF/lib Created directory MailBoxes/src/com/samag Created directory MailBoxes/src/com/samag/client Created directory MailBoxes/src/com/samag/server Created file MailBoxes/src/com/samag/MailBoxes.gwt.xml Created file MailBoxes/war/MailBoxes.html Created file MailBoxes/war/MailBoxes.css Created file MailBoxes/war/WEB-INF/web.xml Created file MailBoxes/src/com/samag/client/MailBoxes.java Created file MailBoxes/src/com/samag/client/GreetingService.java Created file MailBoxes/src/com/samag/client/GreetingServiceAsync.java Created file MailBoxes/src/com/samag/server/GreetingServiceImpl.java Created file MailBoxes/build.xml Created file MailBoxes/README.txt Created file MailBoxes/.project Created file MailBoxes/.classpath Created file MailBoxes/MailBoxes.launch Created file MailBoxes/war/WEB-INF/lib/gwt-servlet.jar Скрипт webAppCreator создал несколько файлов в каталоге MyApplication/, в том числе базовую функциональность "Hello, world" в классе. В корневой папке приложения появился сценарий его сборки, для Ant - build.xml, следовательно, наше приложение уже можно компилировать и запускать. Воспользовавшись вышеописанными командами ant hosted и ant build, мы получим простейшее рабочее AJAX (а как же!) приложение (см. рис. 4). Как видите, оно состоит из поля ввода, куда следует поместить имя, и кнопки "Отправить", после нажатия на которую появляется ответ сервера с приветствием, учитывающим ваши данные. Давайте теперь посмотрим, что у него внутри. GWT-приложения оформлены в виде модулей, их структура подчиняется правилам, сходным с организацией пакетов в Java-приложении. Она определяется в xml-файле (в нашем случае MessageBox.gwt.xml). Как уже говорилось, GWT-приложение состоит из двух основных частей - клиентской и серверной. Клиентский код, как нетрудно догадаться, содержится в MailBoxes/src/com/samag/client/. как и MailBoxes/src/com/samag/server/, он расположен на одном уровне с конфигурационным файлом. В папке MailBoxes/war/ расположены все веб-ресурсы приложения - HTML, CSS, JavaScript файлы. Там же расположена директория WEB-INF, в которой содержатся метаданные и GWT JavaScript-библиотека среды исполнения (GWT run-time JavaScript library). Если мы заглянем в исходный код файла MailBoxes/src/com/samag/client/MailBoxes.java (основного кода нашего приложения), то обнаружим обычный Java-код. Вот кнопка Send: //Создание кнопки final Button sendButton = new Button("Send"); // Привязка её к таблице стилей sendButton.addStyleName("sendButton"); // Добавление в панель приложения RootPanel.get("sendButtonContainer").add(sendButton); Я не собираюсь пересказывать документацию [2], но базовые понятия изложить придется. Основной класс приложения (в нашем случае MailBoxes) реализует интерфейс EntryPoint. Его метод onModuleLoad() вызывается в тот момент, когда веб-страница с встроенным GW- модулем отображается в браузере клиента. Все элементы визуального интерфейса (кнопки, поля ввода, чекбоксы и т.д.) унаследованы от суперкласса Widget. Все эти виджеты компонуются в рамках объекта класса Panel, который, разумеется, сам является виджетом (его аналог в .Swing - Layout). Компоновка в пространстве веб-страницы происходит в элементы контейнера HTML (в данном случае sendButton Container- это id HTML-элемента <td>), в который будет помещена кнопка. Далее добавляется обработчик: class MyHandler implements ClickHandler, KeyUpHandler { public void onClick(ClickEvent event) { sendNameToServer(); } ........................................... } И связывается с кнопкой: MyHandler handler = new MyHandler(); sendButton.addClickHandler(handler); Мне кажется, что всё ясно. Про серверную часть пока речь не ведём, а что касается компиляции в JavaScript/HTML, то сгенерированные JavaScript объекты загружаются в контейнеры, обозначенные в шаблоне HTML-страницы (MailBoxes/war/MailBoxes.html). Поскольку наше приложение сложностью не отличается, то и шаблон довольно прост: <table align="center"> <tr> <td colspan="2" style="font-weight:bold;">Please enter your name:</td> </tr> <tr> <td id="nameFieldContainer"></td> <td id="sendButtonContainer"></td> </tr> </table> Теперь попробуем ввести какой-нибудь новый функционал, например, добавим кнопку Reset, очищающую поле ввода. Прежде всего чуть преобразуем шаблон, добавив нужный контейнер: <table align="center"> <tr> <td colspan="3" style="font-weight:bold;">Please enter your name:</td> </tr> <tr> <td id="nameFieldContainer"></td> <td id="sendButtonContainer"></td> <td id="resContainer"></td> </tr> </table> Теперь в MailBoxes/src/com/samag/client/MailBoxes.java добавляем новый виджет (в терминах данной среды кнопка и прочие функциональные элементы графического интерфейса - это именно виджеты (widgets). После кода создания кнопки Send добавляем строчку: final Button sendButton = new Button("Send"); final Button resButton = new Button("Reset"); Добавим этот виджет на главную панель приложения: RootPanel.get("sendButtonContainer").add(sendButton); RootPanel.get("resContainer").add(resButton); Теперь следует связать кнопку с внешним событием (в данном случае с кликом по кнопке). Для этого в GWT существуют различные интерфейсы. GWT предоставляет несколько интерфейсов Listener для улавливания событий (щелчков мыши, нажатия клавиатуры, изменения содержаний поля ввода и прочие, знакомые по Javascript). Один из них - ClickHandler - отвечает за обработку клика мыши. Напишем его реализацию: resButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { nameField.setText(""); sendButton.setFocus(true); } }); Готово. Компилируем приложение и наслаждаемся новым функционалом. Всё это хорошо, но преимущества нового способа разработки совершенно не очевидны. Не для того мы совершали столько телодвижений, чтобы учить ещё один диалект Java и отлавливать сообщения об ошибках в консоли. Сделаем следующий шаг - подключим к разработке современную IDE. Работа в IDE Eclipce Сначала скачаваем и установливаем плагин для IDE Eclipse (http://code.google.com/intl/ru/eclipse). К слову сказать, если GWT ещё не установлены, это будет сделано на данном этапе автоматически (а заодно и SDK App Engine - средство разработки для платформы Google App Engine). Инсталляция плагина несколько отличается для разных версий IDE. Для Eclipse 3.5 эта процедура выглядит следующим образом: Заходим в Help -> Install New Software. В появившимся окне в поле Work with вводим url: http://dl.google.com/eclipse/plugin/3.5, нажимаем Add. В появившейся форме вводим название для источника обновлений (например, Google Updute) и после подтверждения выбираем необходимые компоненты (см. рис. 5). Поскольку GWT SDK мы уже установили, его можно пропустить. Далее остаётся только пару раз нажать Next и принять лицензионное соглашение. Теперь импортируем наше приложение в IDE. Для этого нажимаем File -> Import, в появившемся окне мастера выбираем General -> Existsing Project into Workspace. В следующем окне в поле Select root directory указываем путь до корня нашего приложения и жмём Finish. Приложение должно появиться в левом окне Eclipse (см. рис. 6). Для включения поддержки GWT щёлкаем на проекте правой кнопкой мыши. И в контекстном меню выбираем Google -> Web Toolkit Setting. В появившемся окошке помечаем чекбокс Use Google Web Toolkit. Если мы ставили GWT SDK не вместе с плагином, то, нажав на ссылку Configure SDK, указываем расположение фрэймворка. Разработка приложения Теперь можно приступить к действительно полезным вещам. В рамках поставленной задачи нам нужно вывести список почтовых ящиков. С возможностью добавления новых, удаления старых, а также активации/деактивации акаунтов. Список ящиков - это, очевидно, таблица. Чтобы выбрать подходящий объект из арсенала GWT, отправляемся в галерею виджетов (http://code.google.com/intl/ru/webtoolkit/doc/1.6/DevGuide.html), представленную в документации фрэймворка, и выбираем наиболее подходящий объект для нашей задачи. В данном случае это будет Grid-реализация абстрактного класса HTMLTable. Включаем его в наше приложение: final Grid mailGrid = new Grid(1,5); mailGrid.setTitle("mailboxes"); При этом вначале надо импортировать класс из соответствующего GWT-пакета: import com.google.gwt.user.client.ui.Grid; В дальнейшем добавления почти любых новых элементов влечет за собой импорт необходимых пакетов, я не буду на этом останавливаться, так как их название подскажет IDE. Если лёгкий путь не для вас и разработка происходит в vi/notepad, можно воспользоваться описанием применяемых нами компонентов в документации. Заполняем первый ряд таблицы (заголовки столбцов): mailGrid.setText(0, 0, "ID"); mailGrid.setText(0, 1, "Name"); mailGrid.setText(0, 2, "Email"); mailGrid.setText(0, 3, "Activity"); Далее заполним таблицу значениями. this.getUsers(mailGrid); По-настоящему такие сведения должны предоставляться по запросу к внешнему источнику (к базе данных или, например, к LDAP), но мы договорились, что сейчас не обращаем внимания на серверную часть кода. Поэтому метод getUsers пока будет своеобразной заглушкой, впрочем, не совсем бестолковой: private void getUsers(Grid grid) { int rows; int newRow; String rid; rows=grid.getRowCount(); newRow=grid.insertRow(rows); grid.setText(newRow, 0, "1"); grid.setText(newRow, 1, "Ivfnov"); grid.setText(newRow,2, "ivanov@gwt.ru"); grid.setText(newRow, 3, "On"); rows=grid.getRowCount(); newRow=grid.insertRow(rows); grid.setText(newRow, 0, "2"); grid.setText(newRow, 1, "Sidorov"); grid.setText(newRow, 2, "sidorov@gwt.ru"); grid.setText(newRow, 3, "On"); Затем создадим в HTML-шаблоне (MailBox.html) необходимый контейнер: <div id="mailTable" align="center"></div> Подключаем нашу таблицу к основной панели приложения: RootPanel.get("mailTable").add(mailGrid); После компиляции мы можем видеть ужасно выглядящую и почти бесполезную таблицу почтовых ящиков (см. рис. 7). Теперь попробуем привести наше приложение к человеческому виду и нормальной функциональности. Первая задача большой сложности не представляет. В GWT по умолчанию для каждого элемента формы есть соответствующий класс, отображение которого задано в таблице стилей. Если мы хотим определить стиль самостоятельно, особых проблем не возникнет. Достаточно воспользоваться соответствующим методом для установки имени стиля: mailGrid.setStyleName("emailTables"); И прописать его с таким названием в таблице стилей (MailBox/war/MailBox.ccs): emailTables{ font-size: 120%; line-height: 1em; background: url(images/hborder.gif) repeat-x; } Любуемся результатом (см. рис. 8) и приступаем к созданию функционала. Сначала обеспечим возможность удаления записи. Создадим виджет кнопки для удаления как самостоятельный класс, производный от класса Button (который в свою очередь произведён от Widget): package com.samag.client; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Grid; public class delButton extends Button { public delButton(final Grid grid,final int row) { super("Delete", new ClickHandler() { public void onClick(ClickEvent event) { Window.alert("Удаляем ряд"+row); grid.removeRow(row); } }); } } Я думаю, что по аналогии с кнопкой Reset тут всё понятно. Новые только обращение к объекту Window, аналогу объекта window веб-страницы, и метод removeRow, который "подсказал" Eclipse. Для того чтобы вставить эту кнопку в список акаунтов, немного изменяем заполнение таблицы: newRow=grid.insertRow(rows); grid.setText(newRow, 0, "1"); grid.setText(newRow, 1, "Иванов"); grid.setText(newRow,2, "ivanov@gwt.ru"); grid.setText(newRow, 3, "On"); grid.setWidget(newRow, 4, new delButton(grid,1)); На следующем этапе сделаем возможным активацию/блокирование акаунтов. Для этого создадим ещё один виджет - кнопку-переключатель, найдя предварительно подходящий класс (ToggleButton) в галерее виджетов: package com.samag.client; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.ToggleButton; import com.google.gwt.user.client.Window; public class ActiveButton extends ToggleButton { public ActiveButton(final Grid grid, int turn) { super("On", "Off"); if(turn!=1){ this.setDown(true); } public void onClick(ClickEvent event) { Window.alert("Меняем активность"); } } Вносим изменение в заполнение таблицы: newRow=grid.insertRow(rows); grid.setText(newRow, 0, "1"); grid.setText(newRow, 1, "Ivanov"); grid.setText(newRow,2, "ivanov@gwt.ru"); grid.setWidget(newRow, 3, new ActiveButton(grid,1)); grid.setWidget(newRow, 4, new delButton(grid,1)); Осталось создать возможность заносить в таблицу новые акаунты. Для этого добавим форму в последнем ряду таблицы. Сначала создадим необходимые виджеты (которые после компиляции станут полями html-формы): final TextBox Name = new TextBox(); final TextBox Email = new TextBox(); final CheckBox Activity = new CheckBox(); Activity.setValue(true); Создаём новый ряд таблицы и заполняем его виджетами: int rows=mailGrid.getRowCount(); int newRow=mailGrid.insertRow(rows); mailGrid.setWidget(newRow, 1, Name); mailGrid.setWidget(newRow, 2, Email); mailGrid.setWidget(newRow, 3, Activity); mailGrid.setWidget(newRow, 4, new Button("Add", new ClickHandler() { public void onClick(ClickEvent event) { this.addRow(mailGrid,Name.getValue(),Email.getValue(),Activity.getValue()); } В последнею ячейку мы помещаем новую кнопку, на этот раз не создавая нового класса, а просто привязывавя к объекту класса Button новый хендлер. Метод addRow, конечно, нуждается в реализации: private void addRow(Grid mailGrid,String uName, String uEmail, Boolean uActivity) { if(uName.isEmpty() && uEmail.isEmpty()){ Window.alert("Не все параметры заполнены!"); return; } int rows=mailGrid.getRowCount(); String rid=String.valueOf(Integer.parseInt(mailGrid.getText(rows-2, 0))+1); int newRow=mailGrid.insertRow(rows-1); mailGrid.setText(newRow, 0, rid); mailGrid.setText(newRow, 1, uName); mailGrid.setText(newRow, 2, uEmail); int turn = 0; if(uActivity.booleanValue()){ turn = 1; } ActiveButton uActive = new ActiveButton(mailGrid,turn); mailGrid.setWidget(newRow, 3, uActive); mailGrid.setWidget(newRow, 4, new delButton(mailGrid,newRow)); } Компилируем и проверяем результат (см. рис. 9). Обратите внимание, как мы совершенно безболезненно перешли с Windows/Chrome на Linux/Firefox. Для первого знакомства с технологией GWT пока достаточно, но за рамками осталось, как всегда, самое интересное - взаимодействие с сервером, передача данных, удалённый вызов процедур, механизм DWR (Direct Web Remoting) и многое другое. Эти вопросы мы рассмотрим во второй части статьи. 1. Домашняя страница проекта - http://code.google.com/intl/ru/webtoolkit 2. Документация по GWT - http://code.google.com/intl/ru/webtoolkit/doc/1.6/DevGuide.html http://code.google.com/intl/ru/webtoolkit/doc/latest/DevGuide.html 3. Доклад "Архитектура Google Web Toolkit: полезные советы по написанию приложений на GWT" на конференции Google Developer Day 2009, Москва - http://www.youtube.com/watch?v=sjyy9WgaObc&feature=channelа Статью можно обсудить на Форуме журнала "Системный администратор" http://www.samag.ru/forum/

<< Предыдущая ИНДЕКС Исправить src / Печать Следующая >>

 Добавить комментарий
Имя:
E-Mail:
Заголовок:
Текст:




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру