GWT教程

GWT RPC 通信

基于 GWT 的应用程序通常由客户端模块和服务器端模块组成。客户端代码在浏览器中运行,服务器端代码在 Web 服务器中运行。客户端代码必须通过网络发出 HTTP 请求才能访问服务器端数据。
RPC,Remote Procedure Call 是 GWT 使用的一种机制,客户端代码可以在其中直接执行服务器端方法。
GWT RPC 基于 servlet。 GWT RPC 是异步的,客户端在通信过程中永远不会被阻塞。 使用 GWT RPC 可以在客户端和服务器之间直接发送 Java 对象(这些对象由 GWT 框架自动序列化)。 服务器端 servlet 称为 服务 从客户端代码调用服务器端 servlet 方法的远程过程调用称为调用服务

GWT RPC 组件

以下是 GWT RPC 通信机制中使用的三个组件
在服务器上运行的远程服务(服务器端 servlet)。 调用该服务的客户端代码。 将在客户端和服务器之间传递的 Java 数据对象。
GWT 客户端和服务器都会自动序列化和反序列化数据,因此开发人员无需序列化/反序列化对象,并且数据对象可以通过 HTTP 传输。
下图显示了 RPC 架构。
GWT RPC 工作流
要开始使用 RPC,我们需要遵循 GWT 约定。

RPC 通信工作流程

第 1 步-创建一个可序列化的模型类

在客户端定义一个可序列化的 java 模型对象。
public class Message implements Serializable {
   ...
   private String message;
   public Message(){};
   public void setMessage(String message) {
      this.message = message;
   }
   ...
}

第 2 步-创建服务接口

在客户端定义一个服务接口,它扩展了列出所有服务方法的 RemoteService。
使用注解@RemoteServiceRelativePath 将服务映射到远程servlet 相对于模块基本URL 的默认路径。
@RemoteServiceRelativePath("message")
public interface MessageService extends RemoteService {
   Message getMessage(String input);
}

第 3 步-创建异步服务接口

定义一个到客户端服务的异步接口(与上面提到的服务位于同一位置),它将在 GWT 客户端代码中使用。
public interface MessageServiceAsync {
   void getMessage(String input, AsyncCallback<Message> callback);
}

第 4 步-创建服务实现 Servlet 类

在服务器端实现接口,该类应该扩展 RemoteServiceServlet 类。
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;
   }
}

步骤 5-更新 Web.xml 以包含 Servlet 声明

编辑 Web 应用程序部署描述符 (web.xml) 以包含 MessageServiceImpl Servlet 声明。
<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>

第 6 步-在应用程序代码中进行远程过程调用

创建服务代理类。
MessageServiceAsync messageService = GWT.create(MessageService.class);
创建 AsyncCallback Handler 来处理 RPC 回调,其中服务器将消息返回给客户端
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()); 
   }	   
}
当用户与 UI 交互时调用远程服务
public class HelloWorld implements EntryPoint {
   ... 
   public void onModuleLoad() {
   ...
      buttonMessage.addClickHandler(new ClickHandler() {			
         @Override
         public void onClick(ClickEvent event) {
            messageService.getMessage(txtName.getValue(), 
            new MessageCallBack());
         }
      });
   ...
   }
}

RPC 通信完整示例

此示例将带您通过简单的步骤来展示 GWT 中的 RPC 通信示例。按照以下步骤更新我们在 GWT-创建应用程序章节中创建的 GWT 应用程序-
步骤 描述
com.tutorialspoint 包下创建一个名为HelloWorld 的项目,如GWT-创建应用程序 章节所述。
HelloWorld.gwt.xmlHelloWorld.cssHelloWorld.htmlHelloWorld.java修改为下面解释。保持其余文件不变。
编译并运行应用程序以验证实现逻辑的结果。
以下是修改后的模块描述符 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>
以下是修改后的样式表文件 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;
}
以下是修改后的HTML主机文件 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>
现在在 src/com.tutorialspoint/client 包中创建 Message.java 文件并将以下内容放入其中
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;
   }
}
现在在 src/com.tutorialspoint/client 包中创建 MessageService.java 文件并将以下内容放入其中
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);
}
现在在 src/com.tutorialspoint/client 包中创建 MessageServiceAsync.java 文件并将以下内容放入其中
package com.tutorialspoint.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface MessageServiceAsync {
   void getMessage(String input, AsyncCallback<Message> callback);
}
现在在 src/com.tutorialspoint/server 包中创建 MessageServiceImpl.java 文件并将以下内容放入其中
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;
   }   
}
更新修改后的 Web 应用程序部署描述符 war/WEB-INF/web.xml 的内容以包含 MessageServiceImpl Servlet 声明。
<?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>
src/com.tutorialspoint/client 包中的 HelloWorld.java 内容替换为以下内容
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);
   }    
} 
一旦您准备好完成所有更改,让我们像在GWT-创建应用程序一章中所做的那样,在开发模式下编译和运行应用程序。如果您的应用程序一切正常,这将产生以下结果-
GWT RPC 演示
昵称: 邮箱:
Copyright © 2022 立地货 All Rights Reserved.
备案号:京ICP备14037608号-4