Máy ứng dụng của Google cho Java: Phần 1: Rồ máy lên!

Xây dựng các ứng dụng sát thủ dựa trên Java, mở rộng được với Máy ứng dụng cho Java

Bạn có nhớ khi mà Máy ứng dụng của Google (Google App Engine) chỉ dành cho những người lập trình Python (Pythonistas) không? Những ngày đen tối. Google Inc đã mở nền tảng điện toán đám mây của mình cho các nhà phát triển Java™ trong tháng 4 năm 2009. Trong loạt bài viết ba phần này, Rick Hightower, một huấn luyện viên và tác giả viết về công nghệ Java giúp bạn bắt đầu với nền tảng tin cậy, vững chãi và đầy vui thú này để phát triển ứng dụng dựa trên Java. Trong bài này, bạn sẽ có được một tổng quan về lý do tại sao Máy ứng dụng của Google cho Java có thể là nền tảng để tiếp tục phát triển những ứng dụng sát thủ (N.D: “killer app” tiếng lóng của các lập trình viên, để chỉ một ứng dụng được viết tài tình, đặc biệt hữu ích, hàm ý nó giống như các sát thủ đối với người chơi những trò chơi điện tử), có khả năng mở rộng cao của bạn, sau đó bắt đầu sử dụng các trình cắm thêm (Plugin) của Google cho Eclipse để xây dựng hai ứng dụng ví dụ: một dựa trên bộ công cụ Web của Google (Google Web Toolkit - GWT) và một dựa trên API Servlet của Java. Bạn sẽ tự mình tìm hiểu Máy ứng dụng của Google cho Java làm nên sự khác biệt như thế nào, cả trong việc xây dựng một ứng dụng từ đầu lẫn trong việc triển khai nó dành cho số người truy cập lên đến năm triệu. (Và đó mới chỉ là phiên bản miễn phí.)

Rick Hightower , Giám đốc, eBlox

Rick Hightower phục vụ với tư cách là giám đốc công nghệ cho Mammatus Inc., một công ty đào tạo chuyên về phát triển điện toán đám mây, GWT, Java EE, Spring và Hibernate. Ông là đồng tác giả của cuốn sách nổi tiếng Các công cụ Java cho lập trình cực biên (Java Tools for Extreme Programming) và tác giả của ấn bản đầu tiên của Struts Live — được tải về nhiều nhất trên TheServerSide.com trong nhiều năm. Ông cũng đã viết các bài báo và các hướng dẫn cho developerWorks của IBM và ở trong Ban biên tập của Tạp chí nhà phát triển Java, cũng như là một cộng tác viên thường xuyên về các chủ đề Java và Groovy trên DZone



28 05 2010

Một ý tưởng cũng giống như chỗ ngứa: bạn cần phải gãi nó và khi đó cảm thấy thỏa mãn hơn. Với vai trò là những nhà phát triển phần mềm, chúng ta dành nhiều thời gian nghĩ ra những ý tưởng cho các loại ứng dụng khác nhau. Thật là vui, phải vậy không? Nhưng cái khó là tìm ra cách để làm cho một sản phẩm phần mềm đơm hoa kết trái. Thật là hài lòng khi tưởng tượng ra một cái gì đó và sau đó tạo ra nó. Còn trái lại (một chỗ ngứa không được gãi) thì đúng là khó chịu thật.

Một lý do làm cho nhiều ứng dụng không bao giờ phát triển được là cần có một cơ sở hạ tầng. Một cơ sở hạ tầng được duy trì tốt thường liên quan đến một đội các nhà quản trị hệ thống, các nhà quản trị cơ sở dữ liệu (DBA) và các kỹ sư mạng, mà cho đến gần đây, vẫn là một hoạt động kinh doanh chủ yếu dành cho người giàu. Thậm chí trả tiền cho một bên thứ ba để cho lưu trú các ứng dụng của bạn cũng không đơn giản: điều gì sẽ xảy ra nếu bỗng nhiên ứng dụng nổi tiếng tăng vọt và có rất nhiều lượt truy cập? Cái gọi là hiệu ứng Slashdot (sự kiện số người truy cập đến trang Web bất thình lình tăng vọt) có thể vứt một ý tưởng tốt vào hố rác, đơn giản vì thật khó dự đoán những đột biến tải.

Tuy nhiên, như chúng ta đều biết, điều đó đang thay đổi. Những tiền đề cho các dịch vụ Web đã phát triển lên và ngày nay nó mang lại cho chúng ta những phương tiện, thông qua điện toán đám mây và người anh em tráng kiện hơn của nó, đó là nền tảng-như là-một dịch vụ (PAAS - platform-as-a-service), để xây dựng, triển khai và phân phối các ứng dụng dễ dàng hơn. Bây giờ, khi bạn viết Twitter (dịch vụ mạng xã hội miễn phí) tiếp theo và triển khai nó trên một nền tảng đám mây, nó sẽ có thể mở rộng, bạn thân mến ạ, mở rộng mãi.

Trong bài viết ba phần này, bạn sẽ học qua thực hành tại sao điện toán đám mây/PAAS là một bước nhảy tiến hóa quan trọng như vậy cho sự phát triển phần mềm, và đồng thời cũng bắt đầu với một nền tảng mới thú vị để phát triển Java: Máy ứng dụng của Google cho Java, hiện đang sẵn có dưới dạng phiên bản xem trước. Tôi sẽ bắt đầu với một tổng quan về Máy ứng dụng (App Engine) cho Java, bao gồm các kiểu dịch vụ ứng dụng mà nó cung cấp. Sau đó bạn sẽ đi thẳng vào một ví dụ ứng dụng — ví dụ đầu tiên trong hai ví dụ — bằng cách sử dụng trình cắm thêm của Google cho Eclipse làm Máy ứng dụng cho Java. Ví dụ ứng dụng đầu tiên sẽ sử dụng sự hỗ trợ của Máy ứng dụng cho Java đối với giao diện lập trình ứng dụng (API) dành cho Servlet Java và ví dụ ứng dụng thứ hai sẽ sử dụng sự hỗ trợ của nó đối với bộ công cụ Web của Google (GWT). Trong Phần 2, bạn sẽ tạo ra một ứng dụng quản lý liên lạc nhỏ bằng cách sử dụng sự hỗ trợ của Máy ứng dụng cho Java đối với các servlet và GWT, tương ứng. Và trong Phần 3, bạn sẽ sử dụng ứng dụng được xây dựng tuỳ chỉnh của bạn để khám phá sự hỗ trợ lưu giữ lâu bền dựa trên Java của Máy ứng dụng cho Java, sự hỗ trợ này dựa trên các đối tượng dữ liệu Java (Java Data Objects-JDO) và API dành cho lưu giữ lâu bền của Java (Java Persistence API - JPA).

Thôi, nói thế là đủ: Hãy rồ máy lên!

Về Máy ứng dụng của Google cho Java

Google (tôi tin rằng cũng là nhà sản xuất một số dạng máy tìm kiếm) đầu tiên đã phát hành Máy ứng dụng của Google trong tháng 4 năm 2008. Thật thất vọng với nhiều nhà phát triển Java, bản phát hành đầu tiên đã thuần túy là lĩnh vực của các lập trình viên Python — những người cho rằng khoảng trống nên được sử dụng cho các khối! (Tôi đã viết một cuốn sách về Python, vì vậy tôi biết rõ). Google đã đáp lại yêu cầu của đông đảo mọi người bằng cách phát hành Máy ứng dụng của Google cho Java trong tháng 4 năm 2009.

Máy ứng dụng của Google cho Java cung cấp một giải pháp xuyên suốt từ đầu đến cuối để phát triển ứng dụng Java doanh nghiệp: một giao diện người dùng đồ họa (GUI) Ajax dựa trên trình duyệt cho dễ sử dụng, hỗ trợ công cụ Eclipse và Máy ứng dụng của Google ở mặt sau. Tính dễ sử dụng và có công cụ đầy đủ cũng là các lợi thế của Máy ứng dụng của Google cho Java so với các giải pháp điện toán đám mây khác.

Phát triển ứng dụng trong Máy ứng dụng cho Java có nghĩa là sử dụng nguồn tài nguyên của Google để lưu trữ và lấy ra các đối tượng Java. Lưu trữ dữ liệu dựa trên BigTable, nhưng với các giao diện JDO và JPA cho phép bạn viết mã mà không bị ràng buộc trực tiếp với BigTable. Trong thực tế, Google cung cấp hỗ trợ dựa trên các tiêu chuẩn cho nhiều API để bạn có thể viết mã mà không bị ràng buộc 100% với nền tảng Máy ứng dụng cho Java.

Máy ứng dụng cho Java dựa trên các Java API tiêu chuẩn sau đây:

  • java.net.URL để tìm nạp các dịch vụ (bằng cách giao tiếp với các máy chủ khác, sử dụng giao thức HTTP và HTTPS).
  • JavaMail để gửi thông điệp thư điện tử.
  • Một giao diện JCache (JSR 107) cho bộ nhớ truy cập nhanh (Memcache) để cung cấp sự lưu trữ phân tán tạm thời, nhanh chóng để lưu trữ trong bộ nhớ truy cập nhanh (caching) các truy vấn và các tính toán.

Triển khai Máy ứng dụng cho Java trên WebSphere/DB2

Khi thông báo khai trương Máy ứng dụng cho Java, các đại diện từ Google và IBM® đã triển khai cùng ứng dụng mẫu như nhau trên DB2®/WebSphere®. IIBM đang làm việc để cung cấp sự hỗ trợ API của Google mức thấp cho Tivoli® LDAP và DB2 sao cho các ứng dụng đã xây dựng với Máy ứng dụng cho Java cũng có thể chạy trên sự xếp chồng nền tảng WebSphere/DB2 của IBM.

Ngoài ra, Máy ứng dụng cho Java cung cấp hỗ trợ cho các dịch vụ ứng dụng sau đây:

  • Xác thực và cấp quyền cho người dùng.
  • CRON
  • Nhập/xuất dữ liệu.
  • Truy cập đến dữ liệu tường lửa.

Nhập/xuất dữ liệu là quan trọng cho việc di chuyển dữ liệu từ các nguồn khác vào ứng dụng của Máy ứng dụng cho Java của bạn. Đây là một cách khác mà bạn không bị ràng buộc với Máy ứng dụng cho Java. Hỗ trợ CRON của Google được dựa trên một URL nội bộ, nhận các truy cập theo một lịch trình nhất định, làm nó trở thành một dịch vụ tốt đẹp mà không có nhiều ràng buộc với Máy ứng dụng cho Java. Cơ chế xác thực và cấp quyền cho người dùng đặc thù riêng cho Máy ứng dụng cho Java, nhưng bạn có thể viết một ServletFilter, một khía cạnh, hoặc trình cắm thêm An ninh Spring để giảm thiểu việc ghép buộc chặt chẽ đó.

Tạo ứng dụng đầu tiên của bạn bằng Máy ứng dụng cho Java

Nếu bạn đọc đến đây thì bạn đã sẵn sàng để bắt đầu xây dựng ứng dụng đầu tiên của bạn bằng Máy ứng dụng cho Java. Bước đầu tiên của bạn là cài đặt trình cắm thêm Google (Plugin Google) cho Eclipse cho Máy ứng dụng cho Java; khi hoàn thành việc này, bạn có thể tiếp tục.

Mở Eclipse IDE của bạn và bạn sẽ thấy ba nút mới trong Eclipse IDE của bạn bên cạnh nút Printer (Máy in): một chữ G trong một quả bóng màu xanh, một G trong một hộp dụng cụ màu đỏ và một hình máy bay phản lực nhỏ của Máy ứng dụng cho Java, như trong Hình 1:

Hình 1. Các nút mới sáng lên trong Eclipse IDE của bạn
Các nút mới sáng lên trong Eclipse IDE của bạn

Đây là những gì các nút đó thực hiện:

  • Quả bóng màu xanh cho phép bạn truy cập vào trình thủ thuật tạo dự án của Máy ứng dụng cho Java.
  • Hộp dụng cụ màu đỏ cho phép bạn biên dịch một dự án GWT.
  • Hình máy bay phản lực nhỏ là chìa khóa của bạn để triển khai một dự án Máy ứng dụng.

Bạn sẽ sử dụng trình thủ thuật tạo dự án để tạo ra hai dự án mới: một dựa vào các servlet và dự án kia được xây dựng bằng cách sử dụng GWT. Bạn sẽ sử dụng chức năng của hộp công cụ để biên dịch một dự án GWT. Bạn sẽ khởi chạy máy bay phản lực nhỏ khi bạn đã sẵn sàng triển khai dự án Máy ứng dụng, làm cho nó hoạt động.

Bây giờ bắt đầu bằng cách tạo ra một dự án của Máy ứng dụng cho Java. Trước tiên, hãy nhấn vào quả bóng màu xanh để truy cập vào trình thủ thuật tạo dự án. Sau đó, tạo một ứng dụng được gọi là SimpleServletApp bằng cách sử dụng gói có tên là gaej.example, như trong Hình 2:

Hình 2. Bắt đầu một dự án mới
Bắt đầu một dự án mới

Chú ý rằng người ta đã bỏ đánh dấu chọn hỗ trợ GWT cho ví dụ đơn giản đầu tiên này. Sau khi bạn hoàn thành bước này, trình thủ thuật tạo dự án sẽ tạo một ứng dụng đơn giản dựa trên servlet có một servlet kiểu “Xin chào thế giới”. Hình 3 cho thấy một ảnh chụp màn hình của dự án đó:

Hình 3. Dự án SimpleServletApp
Dự án SimpleServletApp

Hãy chú ý các tệp JAR được tự động bao gồm cho dự án dựa trên servlet mới này:

  • datanucleus-*.jar: Để truy cập vào kho lưu trữ dữ liệu của Máy ứng dụng cho Java sử dụng JDO tiêu chuẩn hoặc API của BigTable mức thấp.
  • appengine-api-sdk.1.2.0.jar: Để sử dụng các dịch vụ ứng dụng của Máy ứng dụng cho Java chưa chuẩn như An ninh (Security) cho Máy ứng dụng cho Java.
  • geronimo-*.jar: Để sử dụng các Java API tiêu chuẩn như API Quản lý giao dịch Java (JTA- Java Transaction Management API) và JPA.
  • jdo2-api-2.3-SNAPSHOT.jar: Để sử dụng API JDO.

Bạn sẽ học cách sử dụng các API về lưu giữ lâu bền từ Máy ứng dụng cho Java và một số dịch vụ ứng dụng của Máy ứng dụng cho Java bắt đầu trong Phần 2 của bài viết này.

Cũng cần chú ý đến tệp cấu hình thùng chứa thời gian chạy cho Máy ứng dụng của Google, được gọi là appengine.xml. Trong ví dụ này, appengine.xml đang được sử dụng để đặt cấu hình tệp logging.properties để thực hiện đăng nhập với Máy ứng dụng cho Java.

Trước tiên hãy xem xét một ứng dụng servlet của Máy ứng dụng cho Java

Một khi bạn đã cấu hình tất cả mọi thứ trong trình thủ thuật tạo dự án, Máy ứng dụng cho Java đưa ra cho bạn khung sườn của một ứng dụng servlet kiểu Xin chào thế giới (Hello World). Hãy xem mã và sau đó xem cách để chạy ứng dụng này như thế nào khi sử dụng các công cụ Eclipse của Máy ứng dụng cho Java. Điểm vào chính của ứng dụng này là SimpleServletAppServlet, như chỉ ra trong Liệt kê 1:

Liệt kê 1. SimpleServletAppServlet
package gaej.example;

import java.io.IOException;
import javax.servlet.http.*;

@SuppressWarnings("serial")
public class SimpleServletAppServlet extends HttpServlet {
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        resp.setContentType("text/plain");
        resp.getWriter().println("Hello, world");
    }
}

Servlet này được ánh xạ với URI /simpleservletapp trong web.xml, như được hiển thị trong Liệt kê 2:

Liệt kê 2. web.xml
<?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 xmlns="http://java.sun.com/xml/ns/javaee" version="2.5">
    <servlet>
        <servlet-name>simpleservletapp</servlet-name>
        <servlet-class>gaej.example.SimpleServletAppServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>simpleservletapp</servlet-name>
        <url-pattern>/simpleservletapp</url-pattern>
    </servlet-mapping>
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
</web-app>

Trình thủ thuật tạo dự án cũng cung cấp một tệp index.html có một đường liên kết đến servlet mới, như chỉ ra trong Liệt kê 3:

Liệt kê 3. Trình thủ thuật tạo dự án tạo tệp index.html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- The HTML 4.01 Transitional DOCTYPE declaration-->
<!-- above set at the top of the file will set     -->
<!-- the browser's rendering engine into           -->
<!-- "Quirks Mode". Replacing this declaration     -->
<!-- with a "Standards Mode" doctype is supported, -->
<!-- but may lead to some differences in layout.   -->

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    
    <!--                                           -->
    <!-- Any title is fine                         -->
    <!--                                           -->
    <title>Hello App Engine</title>
  </head>

  <!--                                           -->
  <!-- The body can have arbitrary html, or      -->
  <!-- you can leave the body empty if you want  -->
  <!-- to create a completely dynamic UI.        -->
  <!--                                           -->
  <body>
    <h1>Hello App Engine!</h1>
    
    <table>
      <tr>
        <td colspan="2" style="font-weight:bold;">Available Servlets:</td>        
      </tr>
      <tr>
        <td><a href="simpleservletapp"/>SimpleServletAppServlet</td>
      </tr>
    </table>
  </body>
</html>

Còn những gì khác làm việc với Máy ứng dụng cho Java?

Google duy trì một danh sách các công cụ và các khung công tác làm việc tốt với Máy ứng dụng cho Java (xem Tài nguyên). Ví dụ, Máy ứng dụng cho Java hỗ trợ nhiều ngôn ngữ JVM, bao gồm cả BeanShell, Groovy, Scala, JRuby, Jython và Rhino. Vì Máy ứng dụng cho Java hỗ trợ khá nhiều các API Java SE và Java EE — như các Servlet, JSP, JPA, JavaMail và API của Java để xử lý XML (JAXP) — nhiều khung công tác hiện có sẵn sàng hoạt động ngay trong Máy ứng dụng cho Java. Ví dụ, bạn có thể sử dụng khung công tác Spring, mặc dù bạn sẽ cần một vài cách vòng tránh cho Spring ORM. Tapestry, wicket, DWR, Tiles, SiteMesh và Grails cũng làm việc được. Struts 2 làm việc với một miếng vá nhỏ. Một số các khung công tác không làm việc trong Máy ứng dụng cho Java là Hibernate và JDBC (không hỗ trợ cho các cơ sở dữ liệu quan hệ), JMX, Java WebServices, JAX-RPC hay JAX-WS, JCA, JNDI, JMS, EJB và Java RMI.

Bây giờ bạn có một ứng dụng servlet đơn giản được xây dựng khi sử dụng chỉ một số các Java API. Và đó là điểm: Máy ứng dụng cho Java bao bọc chức năng Máy ứng dụng, sử dụng các Java API tiêu chuẩn, cho phép Máy ứng dụng hỗ trợ đông đảo các khung công tác sẵn có cho nền tảng Java.

Triển khai ứng dụng

Để chạy ứng dụng dựa trên servlet của bạn với các công cụ Eclipse của Máy ứng dụng cho Java, đầu tiên nhấn chuột phải vào dự án và chọn trình đơn Run As, sau đó chọn "Web Application" (Ứng dụng Web) có quả bóng màu xanh bên cạnh nó, như trong Hình 4:

Hình 4. Chạy máy chủ phát triển của Máy ứng dụng cho Java
Chạy máy chủ phát triển của Máy ứng dụng cho Java

Bây giờ bạn sẽ có thể chuyển hướng đến http://localhost:8080/simpleservletapp trong trình duyệt của bạn và xem ứng dụng đó với thông báo Xin chào thế giới.

GWT so với các ứng dụng Java Web truyền thống

Khi làm việc trong GWT, bạn biên dịch mã Java thành JavaScript và sau đó chạy GUI ứng dụng Web của bạn trong trình duyệt. Kết quả giống với một ứng dụng GUI truyền thống hơn là một ứng dụng Java Web truyền thống. GWT có một thành phần máy khách chạy trong trình duyệt. Thành phần máy khách này trao đổi với mã phía máy chủ Java của bạn thông qua một tập hợp các lớp Java kiểu RMI do bạn viết ra.

Tạo một Máy ứng dụng cho ứng dụng Java/GWT

Bạn đã có một ý tưởng về cách một ứng dụng servlet đơn giản của Máy ứng dụng cho Java làm việc như thế nào, vì vậy tiếp theo chúng ta hãy khám phá công cụ Eclipse của Máy ứng dụng cho Java dành cho ứng dụng GWT. Bắt đầu bằng cách nhấn vào quả bóng màu xanh trên thanh công cụ của Eclipse IDE để kích hoạt trình thủ thuật tạo dự án của Google. Lần này, đánh dấu chọn hỗ trợ cho GWT, như trong Hình 5:

Hình 5. Tạo một ứng dụng GWT đơn giản với trình thủ thuật tạo dự án của Máy ứng dụng cho Java
Tạo một ứng dụng GWT đơn giản với trình thủ thuật tạo dự án của Máy ứng dụng cho Java

Như bạn thấy trong Hình 6, Máy ứng dụng cho Java cung cấp nhiều tạo phẩm mã cho một ứng dụng GWT hơn là cho một ứng dụng dựa trên servlet đơn giản. Ứng dụng ví dụ là một GUI được làm trong GWT để trao đổi với một ứng dụng dịch vụ lời chào.

Hình 6. Các tạo phẩm mã được cung cấp cho một ứng dụng GWT
Các tạo phẩm mã được cung cấp cho một ứng dụng GWT

Có thêm một JAR nữa cho ứng dụng GWT mà nó là không cần thiết cho một ứng dụng dựa trên servlet, cụ thể là gwt-servlet.jar.

Các tạo phẩm khác như sau:

  • src/gaej/example: SimpleGWTApp.gwt.xml: Bộ mô tả mô đun GWT.
  • src/gaej.example.server: GreetingServiceImpl.java: Triển khai thực hiện dịch vụ lời chào.
  • src/gaej.example.client: GreetingService.java: API đồng bộ cho dịch vụ lời chào.
  • src/gaej.example.client: GreetingServiceAsync.java: API không đồng bộ cho dịch vụ lời chào.
  • src/gaej.example.client: SimpleGWTApp.java: Điểm vào chính và cũng để xây dựng GUI của bộ khởi động.
  • war/WEB-INF: web.xml: Triển khai bộ mô tả để cấu hình GreetingServiceImpl.
  • war: SimpleGWTApp.html: Trang HTML hiển thị GUI của GWT.
  • war: SimpleGWTApp.css: Bảng định kiểu cho GUI của GWT.

Trước khi đi sâu vào kiến trúc và mã nguồn của ứng dụng, hãy xem những gì sẽ xảy ra khi bạn chạy nó. Để chạy ứng dụng, nhấn vào hộp màu đỏ trên thanh công cụ của bạn, sau đó nhấn nút Compile (Biên dịch). Bây giờ nhấn chuột phải vào dự án và chọn mục trình đơn Run As—> Web Application như bạn đã làm trước đó. Lần này, vì bạn đang làm việc trên một ứng dụng GWT, một bàn giao tiếp trong chế độ lưu trú GWT (GWT Hosted Mode Console) và trình duyệt sẽ xuất hiện. Hãy tiếp tục và sử dụng ứng dụng Web để nhập tên của bạn và xem đáp ứng. Tôi đã nhận được đáp ứng như thấy trong Hình 7:

Hình 7. Chạy ứng dụng GWT mẫu
Chạy ứng dụng GWT mẫu

Trong các phần tiếp theo, tôi sẽ hướng dẫn bạn qua ứng dụng ví dụ GWT. Nếu bạn muốn biết thêm về GWT (hoặc học theo một hướng dẫn GWT), xem Tài nguyên.

Bên trong ứng dụng GWT

Dựa vào cấu hình được cung cấp, các công cụ GWT của Eclipse tạo ra một ứng dụng bộ khởi động trình bày một mặt tiền trang HTML (SimpleGWTApp.html, hiển thị trong Liệt kê 10) Nó nạp simplegwtapp.js và simplegwtapp.nocache.js. Đây là mã JavaScript được GWT tạo từ mã Java của bạn, cụ thể là mã đã có trong thư mục src thuộc gói gaej.example.client (xem các Liệt kê 6, 78).

Điểm vào chính cho việc tạo GUI là gaej.example.client.SimpleGWTApp, hiển thị trong Liệt kê 8. Lớp này tạo các phần tử GUI của GWT và kết hợp chúng với các phần tử HTML DOM trên SimpleGWTApp.html (xem Liệt kê 10). SimpleGWTApp.html định nghĩa hai phần tử DOM có tên là nameFieldContainersendButtonContainer (các cột trong một bảng). Lớp SimpleGWTApp sử dụng RootPanel.get("nameFieldContainer") để truy cập ô kết hợp với các phần tử DOM đó và thay thế chúng bằng các phần tử GUI. Lớp SimpleGWTApp sau đó định nghĩa một hộp văn bản và một nút, mà bạn có thể sử dụng để nhập tên của một ai đó và gửi cho họ một lời chào (xem Liệt kê 10).

GWT biết rằng lớp SimpleGWTApp là điểm vào chính cho ứng dụng vì SimpleGWTApp.gwt.xml chỉ rõ nó như vậy bằng phần tử điểm vào.

SimpleGWTApp nối với nút, được gọi là sendButton, sao cho khi nó được nhấn SimpleGWTApp sẽ gọi phương thức greetServer trên GreetingService. Giao diện GreetingService được định nghĩa trong src/gaej.example.client.GreetingService.java (Liệt kê 6).

Vì Ajax vốn là không đồng bộ, nên GWT định nghĩa một giao diện không đồng bộ để truy cập các dịch vụ từ xa. SimpleGWTApp sử dụng giao diện không đồng bộ được được định nghĩa trong src/gaej.example.client.GreetingServiceAsync.java (Liệt kê 7). GreetingServiceImpl (src/gaej.example.server.GreetingServiceImpl.java) thực hiện phương thức greetServer được định nghĩa trong GreetingService (Liệt kê 5). Phương thức GreetingServiceImpl.greetServer trả về một chuỗi (String) mà SimpleGWTApp sử dụng chuỗi đó để hiển thị thông báo lời chào trong hộp thoại do nó tạo ra.

Bộ mô tả mô đun GWT khai báo điểm vào chính cho ứng dụng GUI, cụ thể là gaej.example.client.SimpleGWTApp, như thấy trong Liệt kê 4:

Liệt kê 4. Bộ mô tả mô đun GWT (src/gaej/example/SimpleGWTApp.gwt.xml)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 1.6.4//EN"

"http://google-web-toolkit.googlecode.com/svn/tags/1.6.4/
  distro-source/core/src/gwt-module.dtd">


<module rename-to='simplegwtapp'>
  <!-- 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.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='gaej.example.client.SimpleGWTApp'/>
</module>

GreetingServiceImpl là triển khai thực hiện thực tế của ứng dụng dịch vụ lời chào, được hiển thị trong Liệt kê 5. Nó chạy trên phía máy chủ và mã máy khách gọi nó qua một lời gọi thủ tục từ xa.

Liệt kê 5. Triển khai thực hiện các ứng dụng dịch vụ-lời chào (src/gaej.example.server.GreetingServiceImpl.java)
package gaej.example.server;

import gaej.example.client.GreetingService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

/**
 * The server side implementation of the RPC service.
 */
@SuppressWarnings("serial")
public class GreetingServiceImpl extends RemoteServiceServlet implements
        GreetingService {

    public String greetServer(String input) {
        String serverInfo = getServletContext().getServerInfo();
        String userAgent = getThreadLocalRequest().getHeader("User-Agent");
        return "Hello, " + input + "!<br><br>I am running " + serverInfo
                + ".<br><br>It looks like you are using:<br>" + userAgent;
    }
}

GreetingService, hiển thị trong Liệt kê 6, là giao diện cho lời gọi thủ tục từ xa mà mã máy khách sử dụng:

Liệt kê 6. API đồng bộ (src/gaej.example.client.GreetingService.java)
package gaej.example.client;

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

/**
 * The client side stub for the RPC service.
 */
@RemoteServiceRelativePath("greet")
public interface GreetingService extends RemoteService {
    String greetServer(String name);
}

GreetingServiceAsync là giao diện thực tế mà mã máy khách sẽ sử dụng, như được chỉ ra trong Liệt kê 7. Mỗi phương thức đều cung cấp một đối tượng gọi lại để cho bạn được thông báo một cách không đồng bộ khi gọi cuộc gọi thủ tục từ xa hoàn thành. Dưới cái mui che này, GWT sử dụng Ajax. Khi sử dụng Ajax trên máy khách này, tốt nhất là bạn không chặn máy khách và vì vậy không chặn các cuộc gọi không đồng bộ. Việc chặn máy khách sẽ làm hỏng mục đích sử dụng Ajax.

Liệt kê 7. API không đồng bộ (src/gaej.example.client.GreetingServiceAsync.java)
package gaej.example.client;

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

/**
 * The async counterpart of <code>GreetingService</code>.
 */
public interface GreetingServiceAsync {
    void greetServer(String input, AsyncCallback<String> callback);
}

SimpleGWTApp là nơi mà hầu hết các hành động xảy ra. Nó đăng ký cho các sự kiện GUI, sau đó sẽ gửi các yêu cầu Ajax đến GreetingService này.

Liệt kê 8. Điểm vào chính này cho ứng dụng cũng xây dựng GUI khởi động (src/gaej.example.client.SimpleGWTApp.java)
package gaej.example.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.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.HTML;
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;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class SimpleGWTApp 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.
     */
    public void onModuleLoad() {
        final Button sendButton = new Button("Send");
        final TextBox nameField = new TextBox();
        nameField.setText("GWT User");

        // You 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);

        // 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");
        // You can set the id of a widget by accessing its Element
        closeButton.getElement().setId("closeButton");
        final Label textToServerLabel = new Label();
        final HTML serverResponseLabel = new HTML();
        VerticalPanel dialogVPanel = new VerticalPanel();
        dialogVPanel.addStyleName("dialogVPanel");
        dialogVPanel.add(new HTML("<b>Sending name to the server:</b>"));
        dialogVPanel.add(textToServerLabel);
        dialogVPanel.add(new HTML("<br><b>Server replies:</b>"));
        dialogVPanel.add(serverResponseLabel);
        dialogVPanel.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
        dialogVPanel.add(closeButton);
        dialogBox.setWidget(dialogVPanel);

        // Add a handler to close the DialogBox
        closeButton.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                dialogBox.hide();
                sendButton.setEnabled(true);
                sendButton.setFocus(true);
            }
        });

        // 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() {
                sendButton.setEnabled(false);
                String textToServer = nameField.getText();
                textToServerLabel.setText(textToServer);
                serverResponseLabel.setText("");
                greetingService.greetServer(textToServer,
                        new AsyncCallback<String>() {
                            public void onFailure(Throwable caught) {
                                // Show the RPC error message to the user
                                dialogBox
                                        .setText("Remote Procedure Call - Failure");
                                serverResponseLabel
                                        .addStyleName("serverResponseLabelError");
                                serverResponseLabel.setHTML(SERVER_ERROR);
                                dialogBox.center();
                                closeButton.setFocus(true);
                            }

                            public void onSuccess(String result) {
                                dialogBox.setText("Remote Procedure Call");
                                serverResponseLabel
                                        .removeStyleName("serverResponseLabelError");
                                serverResponseLabel.setHTML(result);
                                dialogBox.center();
                                closeButton.setFocus(true);
                            }
                        });
            }
        }

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

Bộ mô tả triển khai Web (web.xml, như thấy trong Liệt kê 9) ánh xạ GreetingService như một nguồn tài nguyên Web dựa trên servlet. Nó ánh xạ GreetingService dưới tên /simplegwtapp/greet sao cho SimpleGWTApp có thể nạp nó và thực hiện cuộc gọi đến nó. Bộ mô tả triển khai Web cũng biểu thị rằng SimpleGWTApp.html là trang chào mừng cho ứng dụng, như vậy nó luôn luôn nạp.

Liệt kê 9.Bộ mô tả triển khai để đặt cấu hình GreetingServiceImpl (war/WEB-INF/web.xml)
<?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>SimpleGWTApp.html</welcome-file>
  </welcome-file-list>
 
  <!-- Servlets -->
  <servlet>
    <servlet-name>greetServlet</servlet-name>
    <servlet-class>gaej.example.server.GreetingServiceImpl</servlet-class>
  </servlet>
 
  <servlet-mapping>
    <servlet-name>greetServlet</servlet-name>
    <url-pattern>/simplegwtapp/greet</url-pattern>
  </servlet-mapping>

</web-app>

Mặt tiền trang HTML là SimpleGWTApp.html, được hiển thị trong Liệt kê 10. Đây là trang để nạp simplegwtapp.js và simplegwtapp.nocache.js, là mã JavaScript được GWT tạo từ mã Java của bạn. Như đã đề cập ở trên, mã này lưu trữ trong thư mục src thuộc gói gaej.example.client (từ các Liệt kê 6, 78).

Liệt kê 10. Trang HTML để hiển thị GUI của GWT (war/SimpleGWTApp.html)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!-- The HTML 4.01 Transitional DOCTYPE declaration-->
<!-- above set at the top of the file will set     -->
<!-- the browser's rendering engine into           -->
<!-- "Quirks Mode". Replacing this declaration     -->
<!-- with a "Standards Mode" doctype is supported, -->
<!-- but may lead to some differences in layout.   -->

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    <!--                                                               -->
    <!-- Consider inlining CSS to reduce the number of requested files -->
    <!--                                                               -->
    <link type="text/css" rel="stylesheet" href="SimpleGWTApp.css">

    <!--                                           -->
    <!-- Any title is fine                         -->
    <!--                                           -->
    <title>Web Application Starter Project</title>
    
    <!--                                           -->
    <!-- This script loads your compiled module.   -->
    <!-- If you add any GWT meta tags, they must   -->
    <!-- be added before this line.                -->
    <!--                                           -->
    <script type="text/javascript" language="javascript" 
  src="simplegwtapp/simplegwtapp.nocache.js"></script>
  </head>

  <!--                                           -->
  <!-- The body can have arbitrary html, or      -->
  <!-- you can leave the body empty if you want  -->
  <!-- to create a completely dynamic UI.        -->
  <!--                                           -->
  <body>

    <!-- OPTIONAL: include this if you want history support -->
    <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' 
  style="position:absolute;width:0;height:0;border:0"></iframe>

    <h1>Web Application Starter Project</h1>

    <table align="center">
      <tr>
        <td colspan="2" style="font-weight:bold;">Please enter your name:</td> 
      </tr>
      <tr>
        <td id="nameFieldContainer"></td>
        <td id="sendButtonContainer"></td>
      </tr>
    </table>
  </body>
</html>

Với GWT, bạn điều khiển dáng vẻ của ứng dụng của bạn thông qua CSS, như đã chứng tỏ trong Liệt kê 11:

Liệt kê 11. Bảng định kiểu cho GUI của GWT (war/SimpleGWTApp.css)
/** Add css rules here for your application. */


/** Example rules used by the template application (remove for your app) */
h1 {
  font-size: 2em;
  font-weight: bold;
  color: #777777;
  margin: 40px 0px 70px;
  text-align: center;
}

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

/** Most GWT widgets already have a style name defined */
.gwt-DialogBox {
  width: 400px;
}

.dialogVPanel {
  margin: 5px;
}

.serverResponseLabelError {
  color: red;
}

/** Set ids using widget.getElement().setId("idOfElement") */
#closeButton {
  margin: 15px 6px 6px;
}

Triển khai Máy ứng dụng của Google

Một khi bạn đã tạo ra ứng dụng sát thủ tiếp theo của thế giới (vì chúng ta thực sự cần một ứng dụng lời chào thân thiện với người sử dụng), bạn sẽ muốn triển khai nó. Toàn bộ vấn đề sử dụng Máy ứng dụng của Google là bạn có thể triển khai ứng dụng của mình trên cơ sở hạ tầng vững chắc của Google, làm cho nó dễ dàng điều chỉnh hơn. Máy ứng dụng của Google được thiết kế để cung cấp một nền tảng cho việc xây dựng các ứng dụng có thể mở rộng "để phát triển từ một đến hàng triệu người dùng mà không nhức đầu về cơ sở hạ tầng" (như đã nêu trên trang chủ Máy ứng dụng - App Engine). Để sử dụng cơ sở hạ tầng này, bạn cần một tài khoản của Máy ứng dụng của Google cho Java.

Giống như nhiều thứ trong đời, thời gian đầu là miễn phí. Phiên bản miễn phí của Máy ứng dụng cho Java cung cấp cho ứng dụng đã triển khai đủ CPU, băng thông và lượng lưu trữ để phục vụ cho khoảng 5 triệu lượt truy cập trang. Sau đó, cần phải trả tiền khi bạn tiếp tục. (Cũng nên nhớ rằng cái sẵn có khi viết bài này là một bản phát hành xem trước của nền tảng Máy ứng dụng cho Java.)

Một khi bạn nhận được tài khoản, bạn sẽ thấy một danh sách còn bỏ trống các ứng dụng tại trang Web Máy ứng dụng cho Java. Nhấn vào nút Create New Application (Tạo ứng dụng mới) và một biểu mẫu giống như trong Hình 8 sẽ xuất hiện. Nhập tên ứng dụng duy nhất và một mô tả, sau đó bạn sẽ thấy một thông báo xác nhận với mã nhận dạng (identifier) ứng dụng của bạn.

Mã nhận dạng cũng thuộc về tệp app.yaml của ứng dụng của bạn. Lưu ý rằng không thể thay đổi mã nhận dạng. Nếu bạn sử dụng việc xác thực của Google cho các ứng dụng của bạn, thì "GAEj Article For Rick Part 1" sẽ được hiển thị trong trang Sign In (Đăng nhập) khi bạn truy cập vào ứng dụng của mình. Bạn sẽ sử dụng gaejarticleforrick để triển khai các ứng dụng lên Máy ứng dụng của Google bằng trình cắm thêm Eclipse của Máy ứng dụng cho Java.

Hình 8. Tạo ứng dụng mới của Máy ứng dụng cho Java
Tạo ứng dụng mới của Máy ứng dụng cho Java

Sau khi bạn thiết lập mã nhận dạng (ID) của ứng dụng, bạn có thể triển khai ứng dụng của mình từ Eclipse. Đầu tiên, nhấn vào nút của thanh công cụ trông giống như biểu tượng Máy ứng dụng của Google (một động cơ phản lực có cánh và đuôi), như chỉ ra trong Hình 9:

Hình 9. Trình cắm thêm Eclipse của Máy ứng dụng cho Java
Trình cắm thêm Eclipse của Máy ứng dụng cho Java

Bạn có thể cần phải bảo đảm chắc chắn dự án Máy ứng dụng cho Java của bạn được đánh dấu chọn trước khi nhấn vào Deploy (Triển khai) trong hộp thoại như thấy trong Hình 10. Bạn sẽ được nhắc cung cấp mã ủy nhiệm Google của bạn, đó là địa chỉ và tên người dùng thư điện tử của bạn.

Hình 10. Triển khai dự án
Triển khai dự án

Hộp thoại trong Hình 10 có một đường liên kết tới "App Engine Project setting" (Thiết lập dự án Máy ứng dụng). Nhấn vào đường liên kết này (cũng có thể truy cập từ tệp thiết lập dự án) và nhập ID của ứng dụng (trong trường hợp này là gaejarticleforrick), như trong Hình 11. Sau khi bạn điền vào ID của ứng dụng, nhấn OK, rồi nhấn Deploy.

Hình 11. Thiết lập dự án cho máy ứng dụng của Google
Thiết lập dự án cho máy ứng dụng của Google

Sau khi bạn đã triển khai ứng dụng của mình, nó sẽ có sẵn tại http://<application id>.appspot.com/. Bạn cũng có thể thấy ứng dụng này đang hoạt động tại http://gaejarticleforrick.appspot.com/.

Kết luận

Đến đây kết thúc Phần 1 của bài giới thiệu của tôi về Máy ứng dụng của Google cho Java. Cho đến nay, bạn đã thu được một tổng quan về Máy ứng dụng cho Java là gì và đã thực hiện các bước đầu tiên bằng việc sử dụng Trình cắm thêm của Google cho Eclipse của Máy ứng dụng cho Java. Bạn tạo ra hai ứng dụng khởi động nhỏ (một ứng dụng dựa trên servlet còn cái kia dựa trên GWT) và sau đó đã triển khai ứng dụng GWT cho nền tảng của Máy ứng dụng Google này.

Các ví dụ cho đến nay đã chứng tỏ việc tạo công cụ và chức năng giúp Máy ứng dụng dễ dàng tạo và triển khai các ứng dụng Java mở rộng được — tiềm năng lên đến quy mô như của YouTube hoặc Facebook. Trong Phần 2, bạn sẽ tiếp tục khám phá những cơ hội sẵn có cho các nhà phát triển Java làm việc trên Máy ứng dụng cho Java. Rời khỏi các ví dụ ứng dụng đã trình bày trong bài viết này, bạn sẽ xây dựng một ứng dụng quản lý mối liên hệ tùy chỉnh. Ứng dụng này cũng sẽ là trọng tâm của các bài tập trong Phần 3, chúng đi sâu vào kho lưu trữ dữ liệu của Máy ứng dụng cho Java và mặt tiền GUI của nó.

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Công nghệ Java, Nguồn mở
ArticleID=494223
ArticleTitle=Máy ứng dụng của Google cho Java: Phần 1: Rồ máy lên!
publish-date=05282010