Пример фреймворка GWT

Разработка Web-приложений с использованием GWT существенно отличается от использования других фреймворков. GWT использует разделение серверной и клиентской частей кода, а также обеспечивает разработчика Java-интерфейсами приложений (API), которые помогают создавать графические интерфейсы (GUI). Использование фреймворка GWT значительно ближе к разработке десктопных приложений с включением библиотек Swing или SWT, чем обычная разработка Web-приложений. Такой подход позволяет абстрагироваться от HTTP-протокола и HTML DOM-модели.

Для создания нового GWT-проекта в среде Eclipse необходимо в меню File выбрать команду "New | Other | Google | Web Application Project", которая открывает вспомогательное диалоговое окно. Это диалоговое окно можно открыть, выбрав пункт "New Web Application Project ..." всплывающего меню Google в панели инструментов.

В окне настройки приложения определяем наименование проекта, package для исходных кодов, устанавливаем необходимые флаги, проверяем установку флага "Generate project sample code" и нажимаем кнопку Finish. В результате Eclipse создаст новый проект.

Структура вновь созданного GWT примера представлена на следующем скриншоте.

Автоматически сгенерированный пример можно сразу же тестировать. Для запуска приложения на исполнение выбираем в контекстном меню проекта пункт "Run As / Web Application (GWT Super Dev Mode)". В этом случае не требуется установка "GWT Developer Plugin for ..." в браузер.

После того, как сервер стартует открываем вкладку "Development Mode" и выбираем браузер, в котором будем работать с нашим приложением, как это представлено на следующем скриншоте.

Интерфейс нашего первого приложения, автоматически создаваемого фреймворком GWT SDK, изображен на следующем скриншоте.

Первоначально требуется ввести имя пользователя и нажать кнопку "Send" для отправки сообщения серверу. После этого сервер формирует перемещаемое окно приветствия "Remote Procedure Call" с дополнительной информацией, которое браузер отображает ниже компонента ввода.

Описание структуры GWT примера

Папка исходных кодов "src" проекта содержит конфигурационный файл "src/examples/gwt/Welcome.gwt.xml" в XML-формате с корневым тэгом <module>.

Исходный код файла конфигурации .gwt.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.6.0//EN"
  "http://google-web-toolkit.googlecode.com/svn/tags/2.6.0/distro-source/core/src/gwt-module.dtd">
<module rename-to='helloworld'>
  <!-- Inherit the core Web Toolkit stuff.                        -->
  <inherits name='com.google.gwt.user.User'/>

  <!-- Inherit the default GWT style sheet.  You can change       -->
  <!-- the theme of your GWT application by uncommenting          -->
  <!-- any one of the following lines.                            -->
  <inherits name='com.google.gwt.user.theme.clean.Clean'/>
  <!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/--> -->
  <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/--> -->
  <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/-->     -->

  <!-- Other module inherits                                      -->

  <!-- Specify the app entry point class.                         -->
  <entry-point class='examples.client.HelloWorld'/>

  <!-- Specify the paths for translatable code                    -->
  <source path='client'/>
  <source path='shared'/>

  <!-- allow Super Dev Mode -->
  <add-linker name="xsiframe"/>
</module>

Имя программного модуля объявляется с помощью атрибута rename-to корневого тэга <module>.

GWT-приложение организовано в виде модулей, представляющих определенную функциональность. GWT-платформа предоставляет набор стандартных модулей, которые необходимо наследовать приложению. Как минимум необходимо наследовать модуль com.google.gwt.user.User, содержащий базовую функциональность GWT-платформы. Дополнительно в файле конфигурации наследуется модуль темы, com.google.gwt.user.theme.clean.Clean, обеспечивающий стили для GUI-компонентов приложения. Наследование объявляется в конфигурационном файле GWT-модуля приложения с помощью тэга <inherits>.

В конфигурационном файле описывается точка входа в GWT-модуль, который реализует интерфейс com.google.gwt.core.client.EntryPoint и переопределяет его метод onModuleLoad, который вызывается при загрузке GWT-модуля. Точка входа объявляется с помощью тэга <entry-point>.

В тэге <source> конфигурационного файла объявляются пакеты, содержащие классы Java-кода и предназначенные для компиляции в JavaScript-код для выполнения на стороне клиента.

Клиентская часть приложения, пакет .client

Пакет с расширением .client содержит java-классы, выполняемые на стороне клиента. В клиенской части примера размещается главный класс приложения Welcome.java и два интерфейса : интерфейс Web-сервиса (GreetingService.java), поставляющего данные клиенту, и интерфейс (GreetingServiceAsync.java), обеспечивающего асинхронный вызов Web-сервиса на стороне клиента.

Главный класс GWT-приложения Welcome.java, являющейся точкой входа в приложение, реализует интерфейс "implements EntryPoint" и переопределяет метод onModuleLoad(), в котором определен GUI-интерфейс приложения.

Исходный код главного класса Welcome.java

/**
 * Entry point classes define onModuleLoad().
 */
public class HelloWorld implements EntryPoint {
    /**
     * The message displayed to the user when the server cannot be reached or
     * returns an error.
     */
    private static final String SERVER_ERROR = "An error occurred while "
            + "attempting to contact the server. Please check your network "
            + "connection and try again.";

    /**
     * Create a remote service proxy to talk to the server-side Greeting service.
     */
    private final GreetingServiceAsync greetingService = GWT.create(GreetingService.class);

    /**
     * This is the entry point method.
     */
    @Override
    public void onModuleLoad() {
        final Button sendButton = new Button("Send");
        final TextBox nameField = new TextBox();
        nameField.setText("GWT User");
        final Label errorLabel = new Label();

        // We can add style names to widgets
        sendButton.addStyleName("sendButton");

        // Add the nameField and sendButton to the RootPanel
        // Use RootPanel.get() to get the entire body element
        RootPanel.get("nameFieldContainer").add(nameField);
        RootPanel.get("sendButtonContainer").add(sendButton);
        RootPanel.get("errorLabelContainer").add(errorLabel);

        // Focus the cursor on the name field when the app loads
        nameField.setFocus(true);
        nameField.selectAll();

        // Create the popup dialog box
        final DialogBox dialogBox = new DialogBox();
        dialogBox.setText("Remote Procedure Call");
        dialogBox.setAnimationEnabled(true);
        final Button closeButton = new Button("Close");
        . . .
        // Add a handler to close the DialogBox
        closeButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                . . .
            }
        });

        // Create a handler for the sendButton and nameField
        class MyHandler implements ClickHandler, KeyUpHandler {
            /** Fired when the user clicks on the sendButton. */
            public void onClick(ClickEvent event) {
                sendNameToServer();
            }

            /** Fired when the user types in the nameField. */
            public void onKeyUp(KeyUpEvent event) {
                if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
                    sendNameToServer();
                }
            }

            /** Send the name from the nameField to the server and wait for a response. */
            private void sendNameToServer() {
                // First, we validate the input.
                . . .

                // Then, we send the input to the server.
                sendButton.setEnabled(false);
                textToServerLabel.setText(textToServer);
                serverResponseLabel.setText("");
                greetingService.greetServer(textToServer,
                    new AsyncCallback<String>() {
                            public void onFailure(Throwable caught) {
                             . . . 
                            }

                            public void onSuccess(String result) {
                             . . . 
                            }
                        });
            }
        }

        // Add a handler to send the name to the server
        MyHandler handler = new MyHandler();
        sendButton.addClickHandler(handler);
        nameField.addKeyUpHandler(handler);
    }
}

Код класса, генерируемый автоматически, приводится с сокращениями.

GUI-интерфейс GWT-приложения создается из объектов, базовым классом которых является класс com.google.gwt.user.client.ui.Widget. Внешний вид по умолчанию Widget-компонентов может переопределяться с помощью CSS-стилей, которые связываются с Widget-компонентами, используя метод addStyleName() суперкласса com.google.gwt.user.client.ui.UIObject.

GUI-интерфейс GWT-приложения имеет основную корневую панель компоновки, представленную классом com.google.gwt.user.client.ui.RootPanel, экземпляр которого получается статическим методом RootPanel.get(). Такая основная корневая панель связана с тэгом <body> Web-страницы GWT-приложения.

Основная корневая RootPanel-панель может содержать другие корневые RootPanel-панели, связанные с элементами Web-страницы GWT-приложения и экземпляры которых получаются с помощью статического метода RootPanel.get(String id), где id – идентификатор HTML-элемента. Widget-компоненты и Panel-панели добавляются в RootPanel-панели с помощью метода add() класса Panel.

Для взаимодействия с Web-сервисом сервера главный класс GWT-примера использует Proxy-объект "greetingService", создаваемый с помощью статического метода GWT.create(RemoteService service). Интерфейс Web-сервиса на стороне клиента расширяет интерфейс com.google.gwt.user.client.rpc.RemoteService и объявляет методы Web-сервиса, вызываемые клиентом.

Интерфейс, определенный на стороне клиента и обеспечивающий асинхронный вызов Web-сервиса, создан на основе интерфейса Web-сервиса и дополняет методы Web-сервиса аргументом – объектом com.google.gwt.user.client.rpc.AsyncCallback. Интерфейс AsyncCallback содержит методы onSuccess() и onFailure(), автоматически вызываемые в случае успешного завершения асинхронного вызова Web-сервиса и в случае возникновения ошибки соответственно. Результат вызова Web-сервиса содержится как аргумент метода onSuccess().

Серверная часть приложения, пакет .server

Пакет GWT-примера с расширением .server содержит класс, выполняемый на стороне сервера. Созданный средой Eclipse класс GreetingServiceImpl.java расширяюет свойства класса com.google.gwt.user.server.rpc.RemoteServiceServlet и реализуюет интерфейс Web-сервиса. Класс RemoteServiceServlet обеспечивает десериализацию входящих клиентских запросов и сериализацию ответов клиенту.

Общая часть приложения, пакет .shared

Пакет GWT-примера с расширением .shared содержит класс, используемый как на стороне клиента, так и на стороне сервера. Сгенерированный средой Eclipse класс FieldVerifier.java обеспечиваето проверку введенных пользователем данных.

Каталог приложения war

Каталог проекта GWT-приложения "war" содержит папку WEB-INF, а также файлы CSS-стилей и HTML-страницы приложения. HTML-страница GWT-приложения содержит элементы, идентификаторы которых связаны с RootPanel-панелями.

Папка WEB-INF содержит дескриптор web.xml развертывания GWT-приложения на стороне сервера, а также папку lib с библиотекой gwt-servlet.jar, обеспечивающей классы механизма GWT RPC удаленного вызова процедур. Дескриптор web.xml содержит объявления сервлета, представляющего Web-сервис GWT-приложения, относительного пути сервлета и главной Web-страницы GWT-приложения.

  Рейтинг@Mail.ru