Перейти к основному содержимому

Введение в GWT

· 8 мин. чтения

1. Введение

GWT или Google Web Toolkit — это фреймворк для создания высокопроизводительных веб-приложений на Java .

В этом уроке мы сосредоточимся и рассмотрим некоторые из его ключевых возможностей и функций.

2. SDK GWT

SDK содержит библиотеки Java API, компилятор и сервер разработки.

2.1. Java-API

GWT API имеет классы для создания пользовательских интерфейсов, выполнения вызовов сервера, интернационализации, выполнения модульных тестов. Чтобы узнать больше, ознакомьтесь с документацией по Java здесь .

2.2. Компилятор

Проще говоря, компилятор GWT — это транслятор исходного кода из Java-кода в Javascript . Результатом компиляции является Javascript-приложение.

Логика его работы включает вырезание из кода неиспользуемых классов, методов, полей и сокращение названий Javascript.

Благодаря этому преимуществу нам больше не нужно включать библиотеки Ajax в наш проект Javascript. Конечно, также можно установить подсказки при компиляции кода.

Вот некоторые полезные параметры GWTCompiler :

  • -logLevel — установить один из уровней логирования ERROR, WARN, INFO, TRACE, DEBUG, SPAM, ALL .
  • -workdir — рабочий каталог компилятора
  • -gen — каталог для записи сгенерированных файлов
  • -out – каталог выходных файлов
  • -optimize — устанавливает уровень оптимизации компилятора от 0 до 9
  • -style – стиль вывода скрипта OBF, PRETTY или DETAILED
  • -module[s] — имя модулей для компиляции

3. Настройка

Последняя версия SDK доступна на странице загрузки . Остальные настройки доступны на странице « Начало работы».

3.1. Мавен

Чтобы настроить проект с помощью Maven, нам нужно добавить следующие зависимости в pom.xml :

<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-servlet</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-user</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt-dev</artifactId>
<scope>provided</scope>
</dependency>

Библиотека gwt-servlet поддерживает серверные компоненты для вызова конечной точки GWT-RPC. gwt-user содержит Java API, который мы будем использовать для создания нашего веб-приложения . gwt-dev содержит код для компиляции, развертывания или размещения приложения.

Чтобы убедиться, что все зависимости используют одну и ту же версию, нам нужно включить родительскую зависимость GWT:

<dependency>
<groupId>com.google.gwt</groupId>
<artifactId>gwt</artifactId>
<version>2.8.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>

Все артефакты доступны для скачивания на Maven Central .

4. Применение

Давайте создадим простое веб-приложение. Он отправит сообщение на сервер и отобразит ответ.

В общем случае GWT-приложение состоит из серверной и клиентской частей . Клиентская сторона делает HTTP-запрос для подключения к серверу. Чтобы сделать это возможным, GWT использует удаленный вызов процедур или просто механизм RPC.

5. GWT и RPC

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

Сначала создадим интерфейс:

@RemoteServiceRelativePath("greet")
public interface MessageService extends RemoteService {
String sendMessage(String message) throws IllegalArgumentException;
}

Аннотация @RemoteServiceRelativePath сопоставляет службу с относительным URL -адресом /message модуля . MessageService должен расширяться от интерфейса маркера RemoteService для выполнения связи RPC .

Реализация MessageService находится на стороне сервера:

public class MessageServiceImpl extends RemoteServiceServlet 
implements MessageService {

public String sendMessage(String message)
throws IllegalArgumentException {
if (message == null) {
throw new IllegalArgumentException("message is null");
}

return "Hello, " + message + "!<br><br> Time received: "
+ LocalDateTime.now();
}
}

Наш серверный класс является продолжением базового класса сервлетов RemoteServiceServlet . Он автоматически десериализует входящие запросы от клиента и сериализует исходящие ответы от сервера .

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

Для работы на стороне клиента нам нужно создать асинхронную версию нашего сервиса:

public interface MessageServiceAsync {
void sendMessage(String input, AsyncCallback<String> callback)
throws IllegalArgumentException;
}

Здесь мы видим дополнительный аргумент в методе getMessage() . Нам нужна асинхронность , чтобы уведомлять пользовательский интерфейс о завершении асинхронного вызова . Таким образом мы предотвращаем блокировку рабочего потока пользовательского интерфейса.

6. Компоненты и их жизненный цикл

SDK предлагает некоторые элементы пользовательского интерфейса и макеты для разработки графических интерфейсов.

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

  • виджеты компонентовTextBox , TextArea , Button , RadioButton , CheckBox и т. д.

и есть виджеты макета или панели, которые составляют и организуют экран:

  • виджеты панелейHorizontalPanel , VerticalPanel , PopupPanel , TabPanel и т. д.…

Каждый раз, когда мы добавляем в код виджет или любой другой компонент, GWT прилагает все усилия, чтобы связать элемент представления с DOM браузера .

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

7. Точка входа

Давайте внимательно посмотрим на основную точку входа в приложение:

public class Google_web_toolkit implements EntryPoint {

private MessageServiceAsync messageServiceAsync = GWT.create(MessageService.class);

public void onModuleLoad() {
Button sendButton = new Button("Submit");
TextBox nameField = new TextBox();
nameField.setText("Hi there");

sendButton.addStyleName("sendButton");

RootPanel.get("nameFieldContainer").add(nameField);
RootPanel.get("sendButtonContainer").add(sendButton);
}
}

Каждый класс пользовательского интерфейса реализует интерфейс com.google.gwt.core.client.EntryPoint , чтобы пометить его как основную запись для модуля . Он подключается к соответствующему документу HTML, где выполняется код Java.

Мы можем определить компоненты пользовательского интерфейса GWT и назначить их тегам HTML с тем же заданным идентификатором. Класс точки входа переопределяет метод точки входа onModuleLoad() , который вызывается автоматически при загрузке модуля .

Здесь мы создаем компоненты пользовательского интерфейса, регистрируем обработчики событий, модифицируем DOM браузера.

Теперь давайте посмотрим, как мы создадим экземпляр нашего удаленного сервера. Для этого мы используем статический метод GWT.create(MessageService.class) .

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

Здесь мы также определяем виджеты Button и TextBox . Чтобы добавить их в DOM-дерево, мы используем класс RootPanel . Это корневая панель, которая возвращает одноэлементное значение для привязки элементов виджета:

RootPanel.get("sendButtonContainer").add(sendButton);

Во-первых, он получает корневой контейнер, помеченный идентификатором sendButtonContainer . После того, как мы прикрепим sendButton к контейнеру.

8. HTML

Внутри папки /webapp у нас есть файл Google_web_toolkit.html .

Мы можем пометить элементы тега определенными идентификаторами, чтобы фреймворк мог связать их с объектами Java :

<body>
<h1>Sample GWT Application</h1>
<table align="center">
<tr>
<td colspan="2" style="font-weight:bold;">Please enter your message:</td>
</tr>
<tr>
<td id="nameFieldContainer"></td>
<td id="sendButtonContainer"></td>
</tr>
</table>
</body>

Теги <td> с идентификаторами nameFieldContainer и sendButtonContainer будут сопоставлены с компонентами Button и TextBox .

9. Дескриптор главного модуля

Давайте посмотрим на типичную конфигурацию файла дескриптора главного модуля Google_web_toolkit.gwt.xml :

<module rename-to='google_web_toolkit'>
<inherits name='com.google.gwt.user.User'/>
<inherits name='com.google.gwt.user.theme.clean.Clean'/>
<entry-point class='com.foreach.client.Google_web_toolkit'/>
</module>

Мы делаем основные вещи GWT доступными, включив интерфейс com.google.gwt.user.User . Кроме того, мы можем выбрать таблицу стилей по умолчанию для нашего приложения. В данном случае это *.clean.Clean .

Другие доступные параметры стиля: *.dark.Dark , *.standard.Standard , *.chrome.Chrome . com.foreach.client.Google_web_toolkit также отмечен здесь тегом <entry-point /> .

10. Добавление обработчиков событий

Для управления событиями набора текста с помощью мыши или клавиатуры GWT будет использовать некоторые обработчики. Все они расширяются от интерфейса EventHandler и имеют метод с аргументом типа события .

В нашем примере мы регистрируем обработчик события щелчка мыши.

Это будет запускать метод onClick() каждый раз при `` нажатии кнопки:

closeButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
vPanel.hide();
sendButton.setEnabled(true);
sendButton.setFocus(true);
}
});

Здесь мы можем изменить состояние и поведение виджета. В нашем примере мы скрываем vPanel и включаем sendButton .

Другой способ — определить внутренний класс и реализовать необходимые интерфейсы:

class MyHandler implements ClickHandler, KeyUpHandler {

public void onClick(ClickEvent event) {
// send message to the server
}

public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
// send message to the server
}
}
}

В дополнение к ClickHandler мы также включаем здесь интерфейс KeyUpHandler для перехвата событий нажатия клавиш. Здесь внутри метода onKeyUp() мы можем использовать KeyUpEvent , чтобы проверить, нажал ли пользователь клавишу Enter .

А вот как мы используем класс MyHandler для регистрации обоих обработчиков событий:

MyHandler handler = new MyHandler();
sendButton.addClickHandler(handler);
nameField.addKeyUpHandler(handler);

11. Вызов сервера

Теперь мы готовы отправить сообщение на сервер. Выполним удаленный вызов процедуры с помощью асинхронного метода sendMessage() .

Второй параметр метода — интерфейс AsyncCallback<String> , где String — тип возвращаемого значения соответствующего синхронного метода :

messageServiceAsync.sendMessage(textToServer, new AsyncCallback<String>() {
public void onFailure(Throwable caught) {
serverResponseLabel.addStyleName("serverResponseLabelError");
serverResponseLabel.setHTML("server error occurred");
closeButton.setFocus(true);
}

public void onSuccess(String result) {
serverResponseLabel.setHTML(result);
vPanel.setVisible(true);
}
});

Как мы видим, получатель реализует методы onSuccess(String result) и onFailure(Throwable) для каждого типа ответа .

В зависимости от результата ответа мы либо устанавливаем сообщение об ошибке «произошла ошибка сервера», либо отображаем значение результата в контейнере.

12. CSS-стили

При создании проекта с помощью плагина eclipse он автоматически создаст файл Google_web_toolkit.css в каталоге /webapp и свяжет его с основным HTML-файлом.

<link type="text/css" rel="stylesheet" href="Google_web_toolkit.css">

Конечно, мы можем определить пользовательские стили для определенных компонентов пользовательского интерфейса программно:

sendButton.addStyleName("sendButton");

Здесь мы назначаем стиль CSS с именем класса sendButton нашему компоненту sendButton :

.sendButton {
display: block;
font-size: 16pt;
}

13. Результат

В итоге у нас есть вот такое простое веб-приложение:

./e2c584f0d9176bd07117d9d70ee8ad6f.png

Здесь мы отправляем сообщение «Привет!» на сервер и печатаем «Привет, привет!» ответ на экране.

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

В этой быстрой статье мы узнали об основах GWT Framework . После этого мы обсудили архитектуру, жизненный цикл, возможности и различные компоненты его SDK.

В результате мы научились создавать простое веб-приложение.

И, как всегда, полный исходный код руководства доступен на GitHub .