Tạo ứng dụng Kotlin Spring thông qua Google Cloud Platform

1. Giới thiệu

Spring Framework 5.0 đã thêm tính năng hỗ trợ Kotlin chuyên dụng, giúp nhà phát triển Kotlin dễ dàng sử dụng Spring. Do đó, những thay đổi này có nghĩa là các tính năng tích hợp Google Cloud do Spring Cloud GCP cung cấp cũng hoạt động liền mạch trong Kotlin. Trong lớp học lập trình này, bạn sẽ thấy việc bắt đầu sử dụng các dịch vụ của Google Cloud trong các ứng dụng Kotlin của mình dễ dàng như thế nào!

Lớp học lập trình này hướng dẫn cách thiết lập một ứng dụng đăng ký đơn giản bằng Kotlin, minh hoạ cách sử dụng các dịch vụ của GCP, bao gồm: Cloud Pub/SubCloud SQL.

Sản phẩm bạn sẽ tạo ra

Trong lớp học lập trình này, bạn sẽ thiết lập một ứng dụng Kotlin Spring Boot chấp nhận thông tin của người đăng ký, xuất bản thông tin này lên một chủ đề Cloud Pub/Sub và duy trì thông tin này trong cơ sở dữ liệu Cloud MySQL.

Kiến thức bạn sẽ học được

Cách tích hợp với các dịch vụ của Google Cloud trong ứng dụng Kotlin Spring.

Bạn cần có

  • Một dự án trên Google Cloud Platform
  • Một trình duyệt, chẳng hạn như Chrome hoặc Firefox

Bạn sẽ sử dụng hướng dẫn này như thế nào?

Chỉ đọc Đọc và hoàn thành bài tập

Bạn đánh giá thế nào về trải nghiệm xây dựng ứng dụng web HTML/CSS?

Người mới bắt đầu Trung cấp Thành thạo

Bạn đánh giá thế nào về trải nghiệm sử dụng các dịch vụ của Google Cloud Platform?

Người mới bắt đầu Trung cấp Thành thạo

2. Thiết lập và yêu cầu

Thiết lập môi trường theo tốc độ của riêng bạn

  1. Đăng nhập vào Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. (Nếu chưa có tài khoản Gmail hoặc G Suite, bạn phải tạo một tài khoản.)

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

Hãy nhớ mã dự án, một tên duy nhất trên tất cả các dự án trên Google Cloud (tên ở trên đã được sử dụng và sẽ không hoạt động đối với bạn, xin lỗi!). Sau này trong lớp học lập trình này, chúng ta sẽ gọi nó là PROJECT_ID.

  1. Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên của Google Cloud.

Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Hãy nhớ làm theo mọi hướng dẫn trong phần "Dọn dẹp" để biết cách tắt các tài nguyên nhằm tránh bị tính phí ngoài phạm vi hướng dẫn này. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.

Google Cloud Shell

Mặc dù có thể vận hành Google Cloud từ xa trên máy tính xách tay, nhưng trong lớp học lập trình này, chúng ta sẽ sử dụng Google Cloud Shell, một môi trường dòng lệnh chạy trên Cloud.

Kích hoạt Cloud Shell

  1. Trong Cloud Console, hãy nhấp vào Kích hoạt Cloud Shell H7JlbhKGHITmsxhQIcLwoe5HXZMhDlYue4K-SPszMxUxDjIeWfOHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RzVad_4nCa0Zz5LtwBlUZFXFCWFrmrWZLqg1MkZz2LdgUDQ.

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

Nếu chưa từng khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian (bên dưới phần hiển thị đầu tiên) mô tả về Cloud Shell. Nếu vậy, hãy nhấp vào Tiếp tục (và bạn sẽ không bao giờ thấy màn hình này nữa). Sau đây là giao diện của màn hình xuất hiện một lần:

kEPbNAo_w5C_pi9QvhFwWwky1cX8hr_xEMGWySNIoMCdi-Djx9AQRqWn-__DmEpC7vKgUtl-feTcv-wBxJ8NwzzAp7mY65-fi2LJo4twUoewT1SUjd6Y3h81RG3rKIkqhoVlFR-G7w

Quá trình cung cấp và kết nối với Cloud Shell chỉ mất vài giây.

pTv5mEKzWMWp5VBrg2eGcuRPv9dLInPToS-mohlrqDASyYGWnZ_SwE-MzOWHe76ZdCSmw0kgWogSJv27lrQE8pvA5OD6P1I47nz8vrAdK7yR1NseZKJvcxAZrPb8wRxoqyTpD-gbhA

Máy ảo này được trang bị tất cả các công cụ phát triển mà bạn cần. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện hầu hết, nếu không muốn nói là tất cả, công việc trong lớp học lập trình này chỉ bằng một trình duyệt hoặc Chromebook.

Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án đã được đặt thành mã dự án của bạn.

  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list

Đầu ra của lệnh

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

Đầu ra của lệnh

[core]
project = <PROJECT_ID>

Nếu không, bạn có thể đặt nó bằng lệnh sau:

gcloud config set project <PROJECT_ID>

Đầu ra của lệnh

Updated property [core/project].

3. Cung cấp tài nguyên Pub/Sub

Trước tiên, chúng ta cần thiết lập một chủ đề và gói thuê bao Cloud Pub/Sub. Trong ứng dụng này, chúng ta sẽ xuất bản thông tin đăng ký lên một chủ đề Pub/Sub; sau đó, thông tin sẽ được đọc từ chủ đề này và duy trì vào cơ sở dữ liệu.

Trong hướng dẫn này, chúng ta sẽ dựa vào Cloud Shell để cung cấp tài nguyên. Xin lưu ý rằng bạn cũng có thể định cấu hình tài nguyên Pub/Sub thông qua mục Cloud Pub/Sub trong Google Cloud Console.

Trong thiết bị đầu cuối Cloud Shell, trước tiên, hãy bật Pub/Sub API.

$ gcloud services enable pubsub.googleapis.com

Tiếp theo, chúng ta sẽ tạo một chủ đề Pub/Sub tên là registrations cho ứng dụng này. Thông tin đăng ký được gửi qua ứng dụng sẽ được xuất bản vào chủ đề này.

$ gcloud pubsub topics create registrations

Cuối cùng, hãy tạo một gói thuê bao cho chủ đề. Gói thuê bao Pub/Sub cho phép bạn nhận tin nhắn từ một chủ đề.

$ gcloud pubsub subscriptions create registrations-sub --topic=registrations

Giờ đây, bạn đã hoàn tất việc tạo một chủ đề và gói thuê bao Cloud Pub/Sub cho ứng dụng của mình.

4. Tạo một phiên bản và cơ sở dữ liệu Cloud SQL (MySQL)

Đối với ứng dụng mẫu của chúng tôi, bạn cũng cần thiết lập một phiên bản cơ sở dữ liệu để lưu trữ thông tin của người đăng ký. Bước này cũng sẽ dựa vào thiết bị đầu cuối Cloud Shell để cung cấp tài nguyên Cloud SQL. Xin lưu ý rằng bạn cũng có thể xem và định cấu hình các phiên bản Cloud SQL thông qua Google Cloud Console.

Trước tiên, hãy bật Cloud SQL Admin API.

$ gcloud services enable sqladmin.googleapis.com

Tiếp theo, chúng ta sẽ cung cấp một phiên bản Cloud SQL (MySQL). Lệnh này có thể mất chút thời gian.

$ gcloud sql instances create codelab-instance --region=us-east1

Sau khi tạo thành công phiên bản Cloud SQL, hãy tạo một cơ sở dữ liệu mới trong phiên bản có tên là registrants.

$ gcloud sql databases create registrants --instance codelab-instance

Giờ đây, bạn đã hoàn tất việc thiết lập phiên bản Cloud SQL và cơ sở dữ liệu cho ứng dụng của mình.

5. Khởi động một ứng dụng Spring Boot

Giờ đây, chúng ta đã sẵn sàng bắt đầu viết ứng dụng. Các bước tiếp theo sẽ tiếp tục sử dụng Cloud Shell như mô tả trong các bước thiết lập.

Trước tiên, chúng ta sẽ dùng Initializr để tạo mã dàn khung cho dự án. Trong cửa sổ Cloud Shell, hãy chạy:

$ cd ~
$ curl https://start.spring.io/starter.tgz \
  -d language=kotlin \
  -d bootVersion=2.4.0 \
  -d dependencies=web,data-jpa,integration,cloud-gcp-pubsub,thymeleaf \
  -d baseDir=registrations-codelab | tar -xzvf -
$ cd registrations-codelab

Lệnh này tạo một chế độ thiết lập dự án Maven ban đầu cũng như mã giàn giáo cho ứng dụng của bạn trong thư mục registrations-codelab/. Các phần sau đây mô tả những điểm cần chỉnh sửa trong mã để tạo ra một ứng dụng hoạt động.

Trình soạn thảo mã Cloud Shell

Cách dễ nhất để bắt đầu sửa đổi và xem mã trong môi trường Cloud Shell là sử dụng Trình chỉnh sửa mã Cloud Shell tích hợp.

Sau khi mở một phiên bản Cloud Shell, hãy nhấp vào Biểu tượng bút chì để mở trình soạn thảo mã. Trình chỉnh sửa sẽ cho phép bạn sửa đổi trực tiếp các tệp dự án do Initialzr tạo.

cce293b40119c37b.png

6. Cấu hình cơ sở dữ liệu

Trước tiên, hãy định cấu hình ứng dụng để ứng dụng có thể kết nối với cơ sở dữ liệu Cloud MySQL mà bạn đã thiết lập. Các thư viện Spring Cloud GCP cung cấp một trình khởi động Cloud MySQL cung cấp các phần phụ thuộc cần thiết để kết nối với một phiên bản Cloud MySQL.

Thêm phần phụ thuộc spring-cloud-gcp-starter-sql-mysql vào pom.xml của dự án:

registrations-codelab/pom.xml

...
<dependencies>

  ... Other dependencies above ...

  <!-- Add the MySQL starter to the list of dependencies -->
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>spring-cloud-gcp-starter-sql-mysql</artifactId>
  </dependency>
</dependencies>

Ngoài ra, bạn cần sửa đổi tệp cấu hình application.properties để mô tả cấu hình cơ sở dữ liệu. Sao chép các thuộc tính sau vào tệp application.properties.

Tìm tên kết nối phiên bản đến cơ sở dữ liệu của bạn:

$ gcloud sql instances describe codelab-instance \
  --format 'value(connectionName)'

Đầu ra của lệnh này sẽ được dùng trong tệp application.properties để định cấu hình thông tin kết nối.

src/main/resources/application.properties

# Modify this property using the output from the previous command line.
spring.cloud.gcp.sql.instance-connection-name=INSTANCE_CONNECTION_NAME

# Your database name
spring.cloud.gcp.sql.database-name=registrants

# So app starts despite "table already exists" errors.
spring.datasource.continue-on-error=true

# Enforces database initialization
spring.datasource.initialization-mode=always

# Cloud SQL (MySQL) only supports InnoDB, not MyISAM
spring.jpa.database-platform=org.hibernate.dialect.MySQL55Dialect
spring.jpa.hibernate.ddl-auto=create-drop

# This is used if you want to connect to a different database instance
# user other than root; not used in codelab.
# spring.datasource.username=root

# This is used to specify the password of the database user;
# not used in codelab.
# spring.datasource.password=password

Thuộc tính duy nhất mà bạn phải sửa đổi là tên kết nối phiên bản. Giá trị này phải được định dạng dưới dạng giá trị phân cách bằng dấu hai chấm theo dạng: YOUR_GCP_PROJECT_ID:REGION:DATABASE_INSTANCE_NAME.

7. Tạo nội dung tĩnh

Trước tiên, chúng ta sẽ tạo giao diện người dùng cho ứng dụng. Ứng dụng phải có một biểu mẫu cho phép người dùng đăng ký cá nhân và một khung hiển thị cho thấy tất cả những người đăng ký thành công.

Đối với trang chủ, hãy tạo một index.html chứa biểu mẫu đăng ký.

src/main/resources/static/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Registration Sample Application</title>
</head>
<body>

<h1>Registration</h1>

<div>
  <nav>
    <a href="/">Home</a><br>
    <a href="/registrants">Registered People</a><br>
  </nav>

  <p>
    This is a demo registration application which sends user information to a Pub/Sub topic and
    persists it into a MySQL database.
  </p>

  <h2>Register Person</h2>
  <div>
    <form action="/registerPerson" method="post">
      First Name: <input type="text" name="firstName" />
      Last Name: <input type="text" name="lastName" />
      Email: <input type="text" name="email" />
      <input type="submit" value="Submit"/>
    </form>
  </div>
</div>

</body>
</html>

Tiếp theo, chúng ta sẽ tạo một mẫu Thymeleaf có tên là registrants.html để hiển thị người dùng đã đăng ký. Thymeleaf là một khung tạo mẫu mà chúng tôi sử dụng để tạo và phân phát HTML được tạo động. Bạn sẽ thấy mẫu này trông giống như HTML, ngoại trừ việc mẫu này có thêm một số phần tử đánh dấu để xử lý nội dung động. Mẫu này chấp nhận một tham số duy nhất có tên là personsList, chứa tất cả người đăng ký đã đăng ký thông qua ứng dụng.

src/main/resources/templates/registrants.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <title>Registrants List</title>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body>
<h1>Registrants List</h1>
<p>
  This page displays all the people who were registered through the Pub/Sub topic.
  All results are retrieved from the MySQL database.
</p>
<table border="1">
  <tr>
    <th>First Name</th>
    <th>Last Name</th>
    <th>Email</th>
  </tr>
  <tr th:each="person : ${personsList}">
    <td>[[${person.firstName}]]</td>
    <td>[[${person.lastName}]]</td>
    <td>[[${person.email}]]</td>
  </tr>
</table>

</body>
</html>

Đến đây, bạn có thể xác minh rằng nội dung tĩnh đang được phân phát.

Tạo và chạy ứng dụng bằng Maven:

$ ./mvnw spring-boot:run

Nhấp vào nút xem trước trong cửa sổ Cloud Shell và xác minh rằng bạn thấy trang chủ đang được kết xuất. Tuy nhiên, không có chức năng nào trên giao diện người dùng hoạt động vì chúng ta thiếu một bộ điều khiển web. Thông tin này sẽ được thêm vào trong bước tiếp theo.

5e38bb0d0e93002e.png

Sau khi xem trước ứng dụng, hãy nhấn vào CTRL+C để kết thúc ứng dụng.

8. Gửi người đăng ký đến một chủ đề Pub/Sub

Trong bước này, chúng ta sẽ triển khai tính năng mà người đăng ký gửi qua biểu mẫu trực tuyến sẽ được xuất bản lên một chủ đề Cloud Pub/Sub.

Thêm các lớp dữ liệu

Trước tiên, chúng ta sẽ tạo một số lớp dữ liệu Kotlin. Đây sẽ là các thực thể JPA của chúng ta, đồng thời đóng vai trò là bản trình bày trung gian của những người đăng ký được gửi thông qua biểu mẫu.

Trong gói minh hoạ, hãy thêm 2 tệp mới: một lớp Person và một PersonRepository Spring Data. Hai lớp này sẽ giúp chúng ta dễ dàng lưu trữ và truy xuất các mục đăng ký từ cơ sở dữ liệu MySQL bằng Spring Data JPA.

src/main/kotlin/com/example/demo/Person.kt

package com.example.demo

import javax.persistence.Entity
import javax.persistence.GeneratedValue
import javax.persistence.Id

@Entity
data class Person(
    val firstName: String,
    val lastName: String,
    val email: String,
    @Id @GeneratedValue
    var id: Long? = 0)

src/main/kotlin/com/example/demo/PersonRepository.kt

package com.example.demo

import org.springframework.data.repository.CrudRepository

interface PersonRepository : CrudRepository<Person, Long>

Thêm Bộ điều khiển web

Tiếp theo, chúng ta sẽ tạo một lớp Trình điều khiển để xử lý người đăng ký từ biểu mẫu và gửi thông tin đến chủ đề Cloud Pub/Sub mà bạn đã tạo trước đó. Bộ điều khiển này tạo ra 2 điểm cuối:

  • /registerPerson: Điểm cuối POST nơi thông tin của người đăng ký được gửi rồi chuyển đến chủ đề Pub/Sub. Trong hàm registerPerson(..), thông tin của người đăng ký được gửi đến chủ đề Pub/Sub bằng cách sử dụng PubSubTemplate, một lớp tiện ích từ các hoạt động tích hợp Spring Cloud GCP Pub/Sub giúp giảm thiểu mã nguyên mẫu cần thiết để bắt đầu tương tác với Cloud Pub/Sub.
  • /registrants: Hiển thị tất cả những người đăng ký đã đăng ký thành công trong cơ sở dữ liệu. Thông tin này được truy xuất từ thực thể MySQL bằng kho lưu trữ Spring Data mà chúng ta đã tạo ở bước trước.

Tạo lớp Trình điều khiển sau trong gói minh hoạ:

src/main/kotlin/com/example/demo/Controller.kt

package com.example.demo

import com.google.cloud.spring.pubsub.core.PubSubTemplate
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.ModelAndView
import org.springframework.web.servlet.view.RedirectView

@RestController
class Controller(val pubSubTemplate: PubSubTemplate, val personRepository: PersonRepository) {
  
  // The Pub/Sub topic name created earlier.
  val REGISTRATION_TOPIC = "registrations"

  @PostMapping("/registerPerson")
  fun registerPerson(
    @RequestParam("firstName") firstName: String,
    @RequestParam("lastName") lastName: String,
    @RequestParam("email") email: String): RedirectView {

    pubSubTemplate.publish(
        REGISTRATION_TOPIC,
        Person(firstName, lastName, email))
    return RedirectView("/")
  }

  @GetMapping("/registrants")
  fun getRegistrants(): ModelAndView {
    val personsList = personRepository.findAll().toList()
    return ModelAndView("registrants", mapOf("personsList" to personsList))
  }
}

Bộ điều khiển đọc thông tin của người đăng ký được gửi qua biểu mẫu trực tuyến, sau đó xuất bản thông tin đó lên chủ đề Pub/Sub.

Thêm Bean của trình ánh xạ đối tượng JSON

Có thể bạn đã nhận thấy trong Trình điều khiển rằng chúng ta xuất bản một đối tượng Person vào chủ đề Pub/Sub chứ không phải một chuỗi. Điều này có thể thực hiện được vì chúng tôi tận dụng khả năng hỗ trợ Spring Cloud GCP cho các tải trọng JSON tuỳ chỉnh được gửi đến các chủ đề – các thư viện này cho phép bạn chuyển đổi các đối tượng thành JSON, gửi tải trọng JSON đến một chủ đề và chuyển đổi tải trọng khi nhận được.

Để tận dụng tính năng này, bạn phải thêm một thành phần ObjectMapper vào ngữ cảnh ứng dụng của mình. Bean ObjectMapper này sẽ được dùng để chuyển đổi tuần tự các đối tượng thành và từ JSON khi ứng dụng của bạn gửi và nhận thông báo. Trong lớp DemoApplication.kt, hãy thêm JacksonPubSubMessageConverter Spring bean:

src/main/kotlin/com/example/demo/DemoApplication.kt

package com.example.demo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

// new imports to add
import org.springframework.context.annotation.Bean
import com.fasterxml.jackson.databind.ObjectMapper
import com.google.cloud.spring.pubsub.support.converter.JacksonPubSubMessageConverter

@SpringBootApplication
class DemoApplication {
  // This bean enables serialization/deserialization of
  // Java objects to JSON for Pub/Sub payloads
  @Bean
  fun jacksonPubSubMessageConverter(objectMapper: ObjectMapper) = 
      JacksonPubSubMessageConverter(objectMapper)
}

fun main(args: Array<String>) {
        runApplication<DemoApplication>(*args)
}

Đến đây, bạn có thể thử chạy lại ứng dụng bằng cách chạy:

$ ./mvnw spring-boot:run

Từ biểu mẫu trên web ở trang chính, ứng dụng sẽ gửi thông tin đến chủ đề Pub/Sub mà bạn đã tạo. Tuy nhiên, ứng dụng vẫn chưa thực hiện được thao tác hữu ích nào vì chúng ta vẫn cần đọc từ chủ đề Pub/Sub đó! Bạn sẽ thực hiện việc này trong bước tiếp theo.

9. Đọc người đăng ký từ chủ đề Pub/Sub

Trong bước cuối cùng, chúng ta sẽ xử lý thông tin người đăng ký từ chủ đề Pub/Sub và duy trì thông tin đó trong cơ sở dữ liệu Cloud MySQL. Thao tác này sẽ hoàn tất ứng dụng, cho phép bạn gửi người đăng ký mới thông qua biểu mẫu và xem tất cả người dùng đã đăng ký thông qua điểm cuối /registrants.

Ứng dụng này sẽ tận dụng Spring Integration, cung cấp nhiều lớp trừu tượng thuận tiện để xử lý việc nhắn tin. Chúng ta sẽ thêm một PubSubInboundChannelAdapter để cho phép chúng ta đọc các thông báo từ chủ đề Pub/Sub và đặt chúng vào pubsubInputChannel để xử lý thêm. Sau đó, chúng ta sẽ định cấu hình hàm messageReceiver bằng cách sử dụng @ServiceActivator để được gọi bằng các thông báo đến trên pubsubInputChannel.

src/main/kotlin/com/example/demo/DemoApplication.kt

package com.example.demo

import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

import org.springframework.context.annotation.Bean
import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.cloud.gcp.pubsub.support.converter.JacksonPubSubMessageConverter

// new imports to add
import com.google.cloud.spring.pubsub.core.PubSubTemplate
import com.google.cloud.spring.pubsub.integration.AckMode
import com.google.cloud.spring.pubsub.integration.inbound.PubSubInboundChannelAdapter
import com.google.cloud.spring.pubsub.support.BasicAcknowledgeablePubsubMessage
import com.google.cloud.spring.pubsub.support.GcpPubSubHeaders
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.integration.annotation.ServiceActivator
import org.springframework.integration.channel.DirectChannel
import org.springframework.messaging.MessageChannel
import org.springframework.messaging.handler.annotation.Header

@SpringBootApplication
class DemoApplication {

  private val REGISTRANT_SUBSCRIPTION = "registrations-sub"

  @Autowired
  private lateinit var personRepository: PersonRepository

  // New Spring Beans to add
  @Bean
  fun pubsubInputChannel() = DirectChannel()

  @Bean
  fun messageChannelAdapter(
      @Qualifier("pubsubInputChannel") inputChannel: MessageChannel,
      pubSubTemplate: PubSubTemplate): PubSubInboundChannelAdapter {

    val adapter = PubSubInboundChannelAdapter(
        pubSubTemplate, REGISTRANT_SUBSCRIPTION)
    adapter.outputChannel = inputChannel
    adapter.ackMode = AckMode.MANUAL
    adapter.payloadType = Person::class.java
    return adapter
  }

  @ServiceActivator(inputChannel = "pubsubInputChannel")
  fun messageReceiver(
      payload: Person,
      @Header(GcpPubSubHeaders.ORIGINAL_MESSAGE) message: BasicAcknowledgeablePubsubMessage) {
    personRepository.save(payload)
    print("Message arrived! Payload: $payload")
    message.ack()
  }

  // ObjectMapper bean from previous step
  @Bean
  fun jacksonPubSubMessageConverter(objectMapper: ObjectMapper) = JacksonPubSubMessageConverter(objectMapper)
}

fun main(args: Array<String>) {
        runApplication<DemoApplication>(*args)
}

Đến đây, bạn đã hoàn tất quá trình thiết lập cho ứng dụng. Để xác minh rằng ứng dụng hoạt động đúng cách, hãy chạy:

$ ./mvnw spring-boot:run

Nhấp lại vào nút Xem trước rồi thử đăng ký người dùng bằng cách điền thông tin vào biểu mẫu và gửi.

e0d0b0f0c94120c2.png

Nhấp vào đường liên kết Người đăng ký để xác minh rằng người đăng ký mới xuất hiện trong bảng.

ab3b980423d0c51.png

Xin chúc mừng, bạn đã hoàn tất! Kết thúc ứng dụng bằng cách nhấn CTRL+C trong cửa sổ dòng lệnh.

10. Dọn dẹp

Để dọn dẹp môi trường, bạn cần xoá chủ đề Pub/Sub và phiên bản Cloud MySQL mà bạn đã tạo.

Xoá phiên bản Cloud MySQL

$ gcloud sql instances delete codelab-instance

Xoá tài nguyên Pub/Sub

$ gcloud pubsub subscriptions delete registrations-sub
$ gcloud pubsub topics delete registrations

11. Xin chúc mừng!

Giờ đây, bạn đã hoàn tất việc viết một ứng dụng Spring Kotlin tích hợp với Cloud Pub/Sub và Cloud SQL (MySQL).

Tìm hiểu thêm

Giấy phép

Tác phẩm này được cấp phép theo giấy phép Ghi công theo Creative Commons 2.0 Chung.