GWT - RPC-Kommunikation

Eine GWT-basierte Anwendung besteht im Allgemeinen aus einem clientseitigen Modul und einem serverseitigen Modul. Clientseitiger Code wird im Browser und serverseitiger Code im Webserver ausgeführt. Der clientseitige Code muss eine HTTP-Anforderung über das Netzwerk senden, um auf serverseitige Daten zugreifen zu können.

RPC, Remote Procedure Call ist das von GWT verwendete Mechansim, mit dem Clientcode die serverseitigen Methoden direkt ausführen kann.

  • GWT RPC basiert auf Servlets.

  • GWT RPC ist asynchron und der Client wird während der Kommunikation niemals blockiert.

  • Mit GWT RPC können Java-Objekte direkt zwischen dem Client und dem Server gesendet werden (die vom GWT-Framework automatisch serialisiert werden).

  • Das serverseitige Servlet wird als bezeichnet service.

  • Ein Remoteprozeduraufruf, der Methoden von serverseitigen Servlets aus clientseitigem Code aufruft, wird als bezeichnet invoking a service.

GWT RPC-Komponenten

Im Folgenden sind die drei Komponenten aufgeführt, die im GWT-RPC-Kommunikationsmechanismus verwendet werden

  • Ein Remote-Dienst (serverseitiges Servlet), der auf dem Server ausgeführt wird.
  • Client-Code zum Aufrufen dieses Dienstes.
  • Java-Datenobjekte, die zwischen Client und Server übertragen werden.

GWT-Client und -Server serialisieren und deserialisieren Daten automatisch, sodass Entwickler keine Objekte serialisieren / deserialisieren müssen und Datenobjekte über HTTP übertragen werden können.

Das folgende Diagramm zeigt die RPC-Architektur.

Um RPC verwenden zu können, müssen wir die GWT-Konventionen befolgen.

RPC-Kommunikationsworkflow

Schritt 1 - Erstellen Sie eine serialisierbare Modellklasse

Definieren Sie auf der Clientseite ein Java-Modellobjekt, das serialisierbar sein soll.

public class Message implements Serializable {
   ...
   private String message;
   public Message(){};

   public void setMessage(String message) {
      this.message = message;
   }
   ...
}

Schritt 2 - Erstellen Sie eine Serviceschnittstelle

Definieren Sie eine Schnittstelle für den Dienst auf der Clientseite, die den RemoteService erweitert und alle Dienstmethoden auflistet.

Verwenden Sie die Annotation @RemoteServiceRelativePath, um den Dienst mit einem Standardpfad des Remote-Servlets relativ zur Modul-Basis-URL zuzuordnen.

@RemoteServiceRelativePath("message")
public interface MessageService extends RemoteService {
   Message getMessage(String input);
}

Schritt 3 - Erstellen Sie eine Async-Dienstschnittstelle

Definieren Sie eine asynchrone Schnittstelle zum Dienst auf der Clientseite (am selben Speicherort wie der oben erwähnte Dienst), die im GWT-Clientcode verwendet wird.

public interface MessageServiceAsync {
   void getMessage(String input, AsyncCallback<Message> callback);
}

Schritt 4 - Erstellen Sie eine Service Implementation Servlet-Klasse

Implementieren Sie die Schnittstelle auf der Serverseite, und diese Klasse sollte die RemoteServiceServlet-Klasse erweitern.

public class MessageServiceImpl extends RemoteServiceServlet
   implements MessageService{
   ...
   public Message getMessage(String input) {
      String messageString = "Hello " + input + "!";
      Message message = new Message();
      message.setMessage(messageString);
      return message;
   }
}

Schritt 5 - Aktualisieren Sie Web.xml, um die Servlet-Deklaration einzuschließen

Bearbeiten Sie den Deskriptor für die Bereitstellung von Webanwendungen (web.xml), um die Servage-Deklaration MessageServiceImpl einzuschließen.

<web-app>
   ...
   <servlet>
      <servlet-name>messageServiceImpl</servlet-name>
      <servlet-class>com.tutorialspoint.server.MessageServiceImpl
      </servlet-class>
   </servlet>
   
   <servlet-mapping>
      <servlet-name>messageServiceImpl</servlet-name>
      <url-pattern>/helloworld/message</url-pattern>
   </servlet-mapping>
</web-app>

Schritt 6 - Führen Sie den Remoteprozeduraufruf im Anwendungscode durch

Erstellen Sie die Service-Proxy-Klasse.

MessageServiceAsync messageService = GWT.create(MessageService.class);

Erstellen Sie den AsyncCallback-Handler, um den RPC-Rückruf zu verarbeiten, bei dem der Server die Nachricht an den Client zurückgibt

class MessageCallBack implements AsyncCallback<Message> {

   @Override
   public void onFailure(Throwable caught) {
      Window.alert("Unable to obtain server response: "
      + caught.getMessage());	
   }

   @Override
   public void onSuccess(Message result) {
      Window.alert(result.getMessage()); 
   }	   
}

Rufen Sie den Remote-Dienst auf, wenn der Benutzer mit der Benutzeroberfläche interagiert

public class HelloWorld implements EntryPoint {
   ... 
   public void onModuleLoad() {
   ...
      buttonMessage.addClickHandler(new ClickHandler() {			
         @Override
         public void onClick(ClickEvent event) {
            messageService.getMessage(txtName.getValue(), 
            new MessageCallBack());
         }
      });
   ...
   }
}

Beispiel für die vollständige RPC-Kommunikation

Dieses Beispiel führt Sie durch einfache Schritte, um ein Beispiel für eine RPC-Kommunikation in GWT zu zeigen. Führen Sie die folgenden Schritte aus, um die GWT-Anwendung zu aktualisieren, die wir in GWT - Kapitel " Anwendung erstellen" erstellt haben.

Schritt Beschreibung
1 Erstellen Sie ein Projekt mit dem Namen HelloWorld unter einem Paket com.tutorialspoint, wie im Kapitel GWT - Anwendung erstellen erläutert .
2 Ändern Sie HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html und HelloWorld.java wie unten erläutert. Halten Sie den Rest der Dateien unverändert.
3 Kompilieren Sie die Anwendung und führen Sie sie aus, um das Ergebnis der implementierten Logik zu überprüfen.

Es folgt der Inhalt des modifizierten Moduldeskriptors src/com.tutorialspoint/HelloWorld.gwt.xml.

<?xml version = "1.0" encoding = "UTF-8"?>
<module rename-to = 'helloworld'>
   <!-- Inherit the core Web Toolkit stuff.                        -->
   <inherits name = 'com.google.gwt.user.User'/>

   <!-- Inherit the default GWT style sheet.                       -->
   <inherits name = 'com.google.gwt.user.theme.clean.Clean'/>
   <!-- Inherit the UiBinder module.                               -->
   <inherits name = "com.google.gwt.uibinder.UiBinder"/>
   <!-- Specify the app entry point class.                         -->
   <entry-point class = 'com.tutorialspoint.client.HelloWorld'/>
  
   <!-- Specify the paths for translatable code                    -->
   <source path = 'client'/>
   <source path = 'shared'/>

</module>

Im Folgenden finden Sie den Inhalt der geänderten Stylesheet-Datei war/HelloWorld.css.

body {
   text-align: center;
   font-family: verdana, sans-serif;
}

h1 {
   font-size: 2em;
   font-weight: bold;
   color: #777777;
   margin: 40px 0px 70px;
   text-align: center;
}

Es folgt der Inhalt der geänderten HTML-Hostdatei war/HelloWorld.html.

<html>
   <head>
      <title>Hello World</title>
      <link rel = "stylesheet" href = "HelloWorld.css"/>
      <script language = "javascript" src = "helloworld/helloworld.nocache.js">
      </script>
   </head>

   <body>
      <h1>RPC Communication Demonstration</h1>
      <div id = "gwtContainer"></div>
   </body>
</html>

Erstellen Sie nun die Datei Message.java in der src/com.tutorialspoint/client Verpacken und platzieren Sie den folgenden Inhalt darin

package com.tutorialspoint.client;

import java.io.Serializable;

public class Message implements Serializable {
 
   private static final long serialVersionUID = 1L;
   private String message;
   public Message(){};

   public void setMessage(String message) {
      this.message = message;
   }

   public String getMessage() {
      return message;
   }
}

Erstellen Sie nun die Datei MessageService.java in der src/com.tutorialspoint/client Verpacken und platzieren Sie den folgenden Inhalt darin

package com.tutorialspoint.client;

import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;

@RemoteServiceRelativePath("message")
public interface MessageService extends RemoteService {
   Message getMessage(String input);
}

Erstellen Sie nun die Datei MessageServiceAsync.java in der src/com.tutorialspoint/client Verpacken und platzieren Sie den folgenden Inhalt darin

package com.tutorialspoint.client;

import com.google.gwt.user.client.rpc.AsyncCallback;

public interface MessageServiceAsync {
   void getMessage(String input, AsyncCallback<Message> callback);
}

Erstellen Sie nun die Datei MessageServiceImpl.java in der src/com.tutorialspoint/server Verpacken und platzieren Sie den folgenden Inhalt darin

package com.tutorialspoint.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.tutorialspoint.client.Message;
import com.tutorialspoint.client.MessageService;

public class MessageServiceImpl extends RemoteServiceServlet 
   implements MessageService{

   private static final long serialVersionUID = 1L;

   public Message getMessage(String input) {
      String messageString = "Hello " + input + "!";
      Message message = new Message();
      message.setMessage(messageString);
      return message;
   }   
}

Aktualisieren Sie den Inhalt des geänderten Deskriptors für die Bereitstellung von Webanwendungen war/WEB-INF/web.xml um die MessageServiceImpl-Servlet-Deklaration einzuschließen.

<?xml version = "1.0" encoding = "UTF-8"?>
<!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>
   <!-- Default page to serve -->
   <welcome-file-list>
      <welcome-file>HelloWorld.html</welcome-file>
   </welcome-file-list>
   
   <servlet>
      <servlet-name>messageServiceImpl</servlet-name>
      <servlet-class>com.tutorialspoint.server.MessageServiceImpl
      </servlet-class>
   </servlet>

   <servlet-mapping>
      <servlet-name>messageServiceImpl</servlet-name>
      <url-pattern>/helloworld/message</url-pattern>
   </servlet-mapping>
</web-app>

Ersetzen Sie den Inhalt von HelloWorld.java in src/com.tutorialspoint/client Paket mit dem folgenden

package com.tutorialspoint.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DecoratorPanel;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;

public class HelloWorld implements EntryPoint {
	
   private MessageServiceAsync messageService = 
   GWT.create(MessageService.class);

   private class MessageCallBack implements AsyncCallback<Message> {
      @Override
      public void onFailure(Throwable caught) {
         /* server side error occured */
         Window.alert("Unable to obtain server response: " + caught.getMessage());	
      }
      @Override
      public void onSuccess(Message result) {
          /* server returned result, show user the message */
         Window.alert(result.getMessage());
      }	   
   }

   public void onModuleLoad() {
      /*create UI */
      final TextBox txtName = new TextBox(); 
      txtName.setWidth("200");
      txtName.addKeyUpHandler(new KeyUpHandler() {
         @Override
         public void onKeyUp(KeyUpEvent event) {
            if(event.getNativeKeyCode() == KeyCodes.KEY_ENTER){
               /* make remote call to server to get the message */
               messageService.getMessage(txtName.getValue(), 
               new MessageCallBack());
            }				
         }
      });
      Label lblName = new Label("Enter your name: ");

      Button buttonMessage = new Button("Click Me!");

      buttonMessage.addClickHandler(new ClickHandler() {			
         @Override
         public void onClick(ClickEvent event) {
            /* make remote call to server to get the message */
            messageService.getMessage(txtName.getValue(), 
            new MessageCallBack());
         }
      });

      HorizontalPanel hPanel = new HorizontalPanel();	
      hPanel.add(lblName);
      hPanel.add(txtName);
      hPanel.setCellWidth(lblName, "130");

      VerticalPanel vPanel = new VerticalPanel();
      vPanel.setSpacing(10);
      vPanel.add(hPanel);
      vPanel.add(buttonMessage);
      vPanel.setCellHorizontalAlignment(buttonMessage, 
      HasHorizontalAlignment.ALIGN_RIGHT);

      DecoratorPanel panel = new DecoratorPanel();
      panel.add(vPanel);

      // Add widgets to the root panel.
      RootPanel.get("gwtContainer").add(panel);
   }    
}

Wenn Sie mit allen vorgenommenen Änderungen fertig sind, lassen Sie uns die Anwendung im Entwicklungsmodus kompilieren und ausführen, wie wir es im Kapitel GWT - Anwendung erstellen getan haben . Wenn mit Ihrer Anwendung alles in Ordnung ist, führt dies zu folgendem Ergebnis: