Einführung in GWT

1. Einleitung

GWT oder Google Web Toolkit ist ein Framework zum Erstellen leistungsstarker Webanwendungen in Java .

In diesem Tutorial werden wir uns auf einige der wichtigsten Funktionen konzentrieren und diese behandeln.

2. GWT SDK

Das SDK enthält die Java-API-Bibliotheken, einen Compiler und einen Entwicklungsserver.

2.1. Java API

Die GWT-API verfügt über Klassen zum Erstellen von Benutzeroberflächen, zum Ausführen von Serveraufrufen, zur Internationalisierung und zum Durchführen von Komponententests. Weitere Informationen finden Sie in der Java-Dokumentation hier.

2.2. Compiler

Einfach ausgedrückt ist der GWT-Compiler ein Quellübersetzer aus Java-Code in das Javascript . Das Ergebnis der Kompilierung ist eine Javascript-Anwendung.

Die Logik seiner Arbeit umfasst das Trimmen nicht verwendeter Klassen, Methoden, Felder aus dem Code und das Kürzen von Javascript-Namen.

Aufgrund dieses Vorteils müssen wir keine Ajax-Bibliotheken mehr in unser Javascript-Projekt aufnehmen. Natürlich ist es auch möglich, beim Kompilieren des Codes Hinweise zu setzen.

Hier einige nützliche GWTCompiler- Parameter:

  • -logLevel - um einen der Fehler, Warnung, INFO, TRACE, DEBUG, SPAM, alle Protokollebenen
  • -workdir - Arbeitsverzeichnis des Compilers
  • -gen - das Verzeichnis zum Schreiben der generierten Dateien
  • -out - das Ausgabedateiverzeichnis
  • -optimize - Legt die Compiler-Optimierungsstufe von 0 auf 9 fest
  • -style - der Skriptausgabestil OBF, PRETTY oder DETAILED
  • -module [s] - Der Name der zu kompilierenden Module

3. Setup

Das neueste SDK ist auf der Download-Seite verfügbar. Der Rest des Setups ist auf der Seite "Erste Schritte" verfügbar.

3.1. Maven

Um das Projekt mit Maven einzurichten, müssen wir pom.xml die folgenden Abhängigkeiten hinzufügen :

 com.google.gwt gwt-servlet runtime   com.google.gwt gwt-user provided   com.google.gwt gwt-dev provided 

Die gwt-Servlet-Bibliothek unterstützt die serverseitigen Komponenten zum Aufrufen eines GWT-RPC-Endpunkts. gwt-user enthält die Java-API, mit der wir unsere Webanwendung erstellen . gwt-dev hat den Code für den Compiler, die Bereitstellung oder das Hosting der Anwendung.

Um sicherzustellen, dass alle Abhängigkeiten dieselbe Version verwenden, müssen wir die übergeordnete GWT-Abhängigkeit einschließen:

 com.google.gwt gwt 2.8.2 pom import 

Alle Artefakte stehen auf Maven Central zum Download zur Verfügung.

4. Anwendung

Lassen Sie uns eine einfache Webanwendung erstellen. Es wird eine Nachricht an den Server gesendet und die Antwort angezeigt.

Im Allgemeinen besteht eine GWT-Anwendung aus dem Server- und dem Client-Teil . Die Clientseite stellt eine HTTP-Anforderung, um eine Verbindung mit dem Server herzustellen. Um dies zu ermöglichen, verwendet GWT einen Remote Procedure Call oder einfach einen RPC-Mechanismus.

5. GWT und RPC

Zurück zu unserer Anwendung: Lassen Sie uns sehen, wie die RPC-Kommunikation erfolgt. Zu diesem Zweck erstellen wir einen Dienst, um eine Nachricht vom Server zu empfangen.

Erstellen wir zunächst eine Schnittstelle:

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

Die Annotation @RemoteServiceRelativePath ordnet den Dienst der relativen URL des Moduls / message zu . MessageService sollte sich von der RemoteService- Markierungsschnittstelle erstrecken, um die RPC-Kommunikation durchzuführen .

Die Implementierung von MessageService erfolgt serverseitig:

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 + "!

Time received: " + LocalDateTime.now(); } }

Unsere Serverklasse erstreckt sich von der RemoteServiceServlet Basis Servlet - Klasse . Eingehende Anforderungen vom Client werden automatisch deserialisiert und ausgehende Antworten vom Server serialisiert .

Nun wollen wir sehen, wie wir es von der Client-Seite aus verwenden. Der MessageService ist nur eine endgültige Version unseres Service .

Um auf der Clientseite arbeiten zu können, müssen wir die asynchrone Version unseres Dienstes erstellen:

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

Hier sehen wir ein zusätzliches Argument in der Methode getMessage () . Wir benötigen Async , um die Benutzeroberfläche zu benachrichtigen, wenn der asynchrone Aufruf abgeschlossen ist . Auf diese Weise verhindern wir, dass der funktionierende UI-Thread blockiert wird.

6. Komponenten und ihr Lebenszyklus

Das SDK bietet einige Elemente und Layouts der Benutzeroberfläche zum Entwerfen der grafischen Oberflächen.

Im Allgemeinen erstrecken sich alle UI-Komponenten von der Widget- Klasse. Visuell haben wir die Element-Widgets, die wir auf dem Bildschirm sehen, klicken oder verschieben können:

  • Komponenten-Widgets - TextBox , TextArea , Button , RadioButton , CheckBox usw.

und es gibt Layout- oder Bedienfeld-Widgets, die den Bildschirm zusammenstellen und organisieren:

  • Bedienfeld-Widgets - HorizontalPanel , VerticalPanel , PopupPanel , TabPanel usw.

Every time we add a widget or any other component to the code, GWT works hard to link the view element with the browser's DOM.

The constructor always initializes the root DOM element. When we attach a child widget to a parent component, it also causes binding at the DOM level. The entry point class contains the loading function which will be called first. This is where we define our widgets.

7. Entry Point

Let's have a close look at the main entry point of the application:

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); } }

Every UI class implements the com.google.gwt.core.client.EntryPoint interface to mark it as a main entry for the module. It connects to the corresponding HTML document, where the java code executes.

We can define GWT UI components and assign then to HTML tags with the same given ID. Entry point class overrides the entry point onModuleLoad() method, which is called automatically when loading the module.

Here we create the UI components, register event handlers, modify the browser DOM.

Now, let's see how we create our remote server instance. For that purpose, we use GWT.create(MessageService.class) static method.

It determines the requested type at compile-time. Seeing this method, GWT compiler generates many versions of code at compile time, only one of which needs to be loaded by a particular client during bootstrapping at runtime. This feature is widely used in RPC calls.

Here we also define the Button and TextBox widgets. To add attach them into the DOM tree we use the RootPanel class. It is the root panel and returns a singleton value to bind the widget elements:

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

First, it gets the root container marked with sendButtonContainer id. After we attach the sendButton to the container.

8. HTML

Inside of the /webapp folder, we have Google_web_toolkit.html file.

We can mark the tag elements with the specific ids so the framework can bind them into Java objects:


    
Please enter your message:

The tags with nameFieldContainer and sendButtonContainer ids will be mapped to the Button and TextBox components.

9. Main Module Descriptor

Let's have a look at the typical configuration of the Google_web_toolkit.gwt.xml main module descriptor file:

We make core GWT stuff accessible by including the com.google.gwt.user.User interface. Also, we can choose a default style sheet for our application. In this case, it is *.clean.Clean.

The other available styling options are *.dark.Dark, *.standard.Standard, *.chrome.Chrome. The com.baeldung.client.Google_web_toolkit is also marked here with the tag.

10. Adding Event Handlers

To manage the mouse or keyboard typing events, GWT will use some handlers. They all extend from EventHandler interface and have a method with the event type argument.

In our example, we register the mouse click event handler.

This will fire the onClick() method every time thebutton is pushed:

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

Here we can modify the widget state and behavior. In our example, we hide the vPanel and enable the sendButton.

The other way is to define an inner class and implement the necessary interfaces:

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 } } }

In addition to ClickHandler, we also include here the KeyUpHandler interface to catch the keypress events. Here, inside of onKeyUp() method we can use the KeyUpEvent to check if the user pressed the Enter key.

And here how we use the MyHandler class to register both event handlers:

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

11. Calling the Server

Now, we're ready to send the message to the server. We'll perform a remote procedure call with asynchronous sendMessage() method.

The second parameter of the method is AsyncCallback interface, where the String is the return type of the corresponding synchronous method:

messageServiceAsync.sendMessage(textToServer, new AsyncCallback() { 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); } });

As we can see, the receiver implementsonSuccess(String result)and onFailure(Throwable)method for each response type.

Depending on response result, we either set an error message “server error occurred” or display the result value in the container.

12. CSS Styling

When creating the project with the eclipse plugin, it will automatically generate the Google_web_toolkit.css file under the /webapp directory and link it to the main HTML file.

Natürlich können wir benutzerdefinierte Stile für die spezifischen UI-Komponenten programmgesteuert definieren:

sendButton.addStyleName("sendButton");

Hier weisen wir unserer sendButton- Komponente einen CSS-Stil mit dem Klassennamen sendButton zu :

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

13. Ergebnis

Als Ergebnis haben wir diese einfache Webanwendung:

Hier senden wir eine "Hallo" -Nachricht an den Server und drucken die "Hallo, Hallo!" - Nachricht aus. Antwort auf dem Bildschirm.

14. Schlussfolgerung

In diesem kurzen Artikel haben wir die Grundlagen von GWT Framework kennengelernt . Anschließend diskutierten wir die Architektur, den Lebenszyklus, die Funktionen und die verschiedenen Komponenten des SDK.

Als Ergebnis haben wir gelernt, wie man eine einfache Webanwendung erstellt.

Und wie immer ist der vollständige Quellcode des Tutorials auf GitHub verfügbar.