GWT - Giao tiếp RPC
Một ứng dụng dựa trên GWT thường bao gồm mô-đun phía máy khách và mô-đun phía máy chủ. Mã phía máy khách chạy trong trình duyệt và mã phía máy chủ chạy trong máy chủ web. Mã phía máy khách phải thực hiện một yêu cầu HTTP qua mạng để truy cập dữ liệu phía máy chủ.
RPC, Lệnh gọi thủ tục từ xa là cơ chế được GWT sử dụng trong đó mã máy khách có thể trực tiếp thực thi các phương thức phía máy chủ.
GWT RPC dựa trên servlet.
GWT RPC là không đồng bộ và máy khách không bao giờ bị chặn trong quá trình giao tiếp.
Sử dụng GWT RPC Các đối tượng Java có thể được gửi trực tiếp giữa máy khách và máy chủ (được tự động tuần tự hóa bởi khung GWT).
Servlet phía máy chủ được gọi là service.
Lệnh gọi thủ tục từ xa đang gọi các phương thức của các servlet phía máy chủ từ mã phía máy khách được gọi là invoking a service.
Các thành phần GWT RPC
Sau đây là ba thành phần được sử dụng trong cơ chế giao tiếp GWT RPC
- Một dịch vụ từ xa (servlet phía máy chủ) chạy trên máy chủ.
- Mã khách hàng để gọi dịch vụ đó.
- Các đối tượng dữ liệu Java sẽ được chuyển giữa máy khách và máy chủ.
Máy khách và máy chủ GWT đều tự động tuần tự hóa và giải mã hóa dữ liệu, vì vậy các nhà phát triển không bắt buộc phải tuần tự hóa / giải mã hóa các đối tượng và các đối tượng dữ liệu có thể di chuyển qua HTTP.
Sơ đồ sau thể hiện Kiến trúc RPC.
Để bắt đầu sử dụng RPC, chúng tôi bắt buộc phải tuân theo các quy ước GWT.
Quy trình giao tiếp RPC
Bước 1 - Tạo một lớp mô hình có thể nối tiếp hóa
Xác định một đối tượng mô hình java ở phía máy khách có thể được tuần tự hóa.
public class Message implements Serializable {
...
private String message;
public Message(){};
public void setMessage(String message) {
this.message = message;
}
...
}
Bước 2 - Tạo giao diện dịch vụ
Xác định giao diện cho dịch vụ ở phía máy khách mở rộng RemoteService liệt kê tất cả các phương thức dịch vụ.
Sử dụng chú thích @RemoteServiceRelativePath để ánh xạ dịch vụ với đường dẫn mặc định của servlet từ xa liên quan đến URL cơ sở của mô-đun.
@RemoteServiceRelativePath("message")
public interface MessageService extends RemoteService {
Message getMessage(String input);
}
Bước 3 - Tạo giao diện dịch vụ không đồng bộ
Xác định giao diện không đồng bộ cho dịch vụ ở phía máy khách (tại cùng vị trí với dịch vụ được đề cập ở trên) sẽ được sử dụng trong mã máy khách GWT.
public interface MessageServiceAsync {
void getMessage(String input, AsyncCallback<Message> callback);
}
Bước 4 - Tạo lớp Servlet triển khai dịch vụ
Triển khai giao diện ở phía máy chủ và lớp đó sẽ mở rộng lớp 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;
}
}
Bước 5 - Cập nhật Web.xml để bao gồm khai báo Servlet
Chỉnh sửa bộ mô tả triển khai ứng dụng web (web.xml) để bao gồm khai báo 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>
Bước 6 - Thực hiện cuộc gọi thủ tục từ xa trong Mã ứng dụng
Tạo lớp proxy dịch vụ.
MessageServiceAsync messageService = GWT.create(MessageService.class);
Tạo AsyncCallback Handler để xử lý lệnh gọi lại RPC trong đó máy chủ trả lại Thông báo cho máy khách
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());
}
}
Gọi dịch vụ từ xa khi người dùng tương tác với giao diện người dùng
public class HelloWorld implements EntryPoint {
...
public void onModuleLoad() {
...
buttonMessage.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
messageService.getMessage(txtName.getValue(),
new MessageCallBack());
}
});
...
}
}
Ví dụ hoàn chỉnh về giao tiếp RPC
Ví dụ này sẽ hướng dẫn bạn qua các bước đơn giản để hiển thị ví dụ về Giao tiếp RPC trong GWT. Làm theo các bước sau để cập nhật ứng dụng GWT mà chúng tôi đã tạo trong GWT - Chương Tạo ứng dụng -
Bươc | Sự miêu tả |
---|---|
1 | Tạo một dự án với tên HelloWorld trong một gói com.tutorialspoint như được giải thích trong chương GWT - Tạo ứng dụng . |
2 | Sửa đổi HelloWorld.gwt.xml , HelloWorld.css , HelloWorld.html và HelloWorld.java như được giải thích bên dưới. Giữ phần còn lại của các tệp không thay đổi. |
3 | Biên dịch và chạy ứng dụng để xác minh kết quả của logic được triển khai. |
Sau đây là nội dung của bộ mô tả mô-đun đã sửa đổi 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>
Sau đây là nội dung của tệp Style Sheet đã sửa đổi 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;
}
Sau đây là nội dung của tệp máy chủ HTML đã sửa đổi 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>
Bây giờ, hãy tạo tệp Message.java trong src/com.tutorialspoint/client gói và đặt các nội dung sau vào đó
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;
}
}
Bây giờ hãy tạo tệp MessageService.java trong src/com.tutorialspoint/client gói và đặt các nội dung sau vào đó
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);
}
Bây giờ hãy tạo tệp MessageServiceAsync.java trong src/com.tutorialspoint/client gói và đặt các nội dung sau vào đó
package com.tutorialspoint.client;
import com.google.gwt.user.client.rpc.AsyncCallback;
public interface MessageServiceAsync {
void getMessage(String input, AsyncCallback<Message> callback);
}
Bây giờ hãy tạo tệp MessageServiceImpl.java trong src/com.tutorialspoint/server gói và đặt các nội dung sau vào đó
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;
}
}
Cập nhật nội dung của bộ mô tả triển khai ứng dụng web đã sửa đổi war/WEB-INF/web.xml để bao gồm khai báo 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>
Thay thế nội dung của HelloWorld.java trong src/com.tutorialspoint/client gói với những thứ sau
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);
}
}
Khi bạn đã sẵn sàng với tất cả các thay đổi được thực hiện, hãy để chúng tôi biên dịch và chạy ứng dụng ở chế độ phát triển như chúng tôi đã làm trong chương GWT - Tạo ứng dụng . Nếu mọi thứ đều ổn với ứng dụng của bạn, điều này sẽ tạo ra kết quả sau: