1. مقدمه
Spring Framework 5.0 پشتیبانی اختصاصی Kotlin را اضافه کرد که استفاده از Spring را برای توسعه دهندگان Kotlin آسان می کند. در نتیجه، این تغییرات به این معنی است که ادغامهای Google Cloud ارائهشده توسط Spring Cloud GCP نیز بهطور یکپارچه در Kotlin کار میکنند. در این لبه کد خواهید دید که شروع استفاده از خدمات Google Cloud در برنامه های Kotlin چقدر آسان است!
این نرم افزار کد از طریق راه اندازی یک برنامه ثبت نام ساده در Kotlin می گذرد که استفاده از خدمات GCP از جمله: Cloud Pub/Sub و Cloud SQL را نشان می دهد.
چیزی که خواهی ساخت
در این نرم افزار کد، شما یک برنامه Kotlin Spring Boot را راه اندازی می کنید که اطلاعات ثبت نام کننده را می پذیرد، آن را در یک موضوع Cloud Pub/Sub منتشر می کند و آن را در پایگاه داده Cloud MySQL ادامه می دهد.
چیزی که یاد خواهید گرفت
نحوه ادغام با خدمات Google Cloud در برنامه Kotlin Spring.
آنچه شما نیاز دارید
- یک پروژه Google Cloud Platform
- یک مرورگر، مانند کروم یا فایرفاکس
چگونه از این آموزش استفاده خواهید کرد؟
تجربه خود را با ساختن برنامه های وب HTML/CSS چگونه ارزیابی می کنید؟
تجربه خود را در استفاده از سرویسهای پلتفرم ابری Google چگونه ارزیابی میکنید؟
2. راه اندازی و الزامات
تنظیم محیط خود به خود
- به کنسول Cloud وارد شوید و یک پروژه جدید ایجاد کنید یا از یک موجود استفاده مجدد کنید. (اگر قبلاً یک حساب Gmail یا G Suite ندارید، باید یک حساب ایجاد کنید .)
شناسه پروژه را به خاطر بسپارید، یک نام منحصر به فرد در تمام پروژه های Google Cloud (نام بالا قبلاً گرفته شده است و برای شما کار نخواهد کرد، متأسفیم!). بعداً در این آزمایشگاه کد به عنوان PROJECT_ID
نامیده خواهد شد.
- در مرحله بعد، برای استفاده از منابع Google Cloud، باید صورتحساب را در Cloud Console فعال کنید .
اجرا کردن از طریق این کد لبه نباید هزینه زیادی داشته باشد، اگر اصلاً باشد. حتماً دستورالعملهای موجود در بخش «تمیز کردن» را دنبال کنید که به شما توصیه میکند چگونه منابع را خاموش کنید تا بیش از این آموزش متحمل صورتحساب نشوید. کاربران جدید Google Cloud واجد شرایط برنامه آزمایشی رایگان 300 دلاری هستند.
Google Cloud Shell
در حالی که Google Cloud را می توان از راه دور از لپ تاپ شما کار کرد، در این کد لبه از Google Cloud Shell استفاده خواهیم کرد، یک محیط خط فرمان که در Cloud اجرا می شود.
Cloud Shell را فعال کنید
- از Cloud Console، روی Activate Cloud Shell کلیک کنید .
اگر قبلاً Cloud Shell را راهاندازی نکردهاید، با یک صفحه میانی (زیر تاشو) روبرو میشوید که آن را توصیف میکند. اگر اینطور است، روی Continue کلیک کنید (و دیگر آن را نخواهید دید). در اینجا به نظر می رسد که آن صفحه یک بار مصرف:
تهیه و اتصال به Cloud Shell فقط باید چند لحظه طول بکشد.
این ماشین مجازی با تمام ابزارهای توسعه که شما نیاز دارید بارگذاری شده است. این دایرکتوری اصلی 5 گیگابایتی دائمی را ارائه می دهد و در Google Cloud اجرا می شود و عملکرد شبکه و احراز هویت را بسیار افزایش می دهد. بیشتر، اگر نه همه، کار شما در این کد لبه را می توان به سادگی با یک مرورگر یا Chromebook انجام داد.
پس از اتصال به Cloud Shell، باید ببینید که قبلاً احراز هویت شده اید و پروژه قبلاً روی ID پروژه شما تنظیم شده است.
- برای تایید احراز هویت، دستور زیر را در Cloud Shell اجرا کنید:
gcloud auth list
خروجی فرمان
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
gcloud config list project
خروجی فرمان
[core] project = <PROJECT_ID>
اگر اینطور نیست، می توانید آن را با این دستور تنظیم کنید:
gcloud config set project <PROJECT_ID>
خروجی فرمان
Updated property [core/project].
3. تامین منابع Pub/Sub
ابتدا باید یک موضوع و اشتراک در Cloud Pub/Sub تنظیم کنیم. در این برنامه، ما اطلاعات ثبت نام را در یک موضوع Pub/Sub منتشر خواهیم کرد. سپس اطلاعات از این موضوع خوانده می شود و در پایگاه داده باقی می ماند.
در این آموزش، ما برای تامین منابع خود به Cloud Shell تکیه خواهیم کرد. توجه داشته باشید که میتوانید منابع Pub/Sub را از طریق بخش Cloud Pub/Sub در Google Cloud Console پیکربندی کنید.
در ترمینال Cloud Shell خود، ابتدا Pub/Sub API را فعال کنید.
$ gcloud services enable pubsub.googleapis.com
در مرحله بعد، یک موضوع Pub/Sub با نام registrations
نام برای این برنامه ایجاد می کنیم. اطلاعات ثبت نام ارسال شده از طریق اپلیکیشن در این تاپیک منتشر خواهد شد.
$ gcloud pubsub topics create registrations
در نهایت یک اشتراک برای موضوع ایجاد کنید. اشتراک Pub/Sub به شما امکان می دهد پیام هایی را از یک موضوع دریافت کنید.
$ gcloud pubsub subscriptions create registrations-sub --topic=registrations
اکنون ایجاد یک موضوع Cloud Pub/Sub و اشتراک برای برنامه خود را تکمیل کرده اید.
4. یک نمونه و پایگاه داده Cloud SQL (MySQL) ایجاد کنید
برای برنامه نمونه خود، ما همچنین باید یک نمونه پایگاه داده را برای نگهداری اطلاعات ثبت کننده تنظیم کنیم. این مرحله همچنین به ترمینال Cloud Shell برای تامین منابع Cloud SQL متکی است. توجه داشته باشید که میتوانید نمونههای Cloud SQL خود را از طریق Google Cloud Console نیز مشاهده و پیکربندی کنید.
ابتدا Cloud SQL Admin API را فعال کنید.
$ gcloud services enable sqladmin.googleapis.com
در مرحله بعد، ما یک نمونه Cloud SQL (MySQL) ارائه خواهیم کرد. این دستور ممکن است کمی طول بکشد.
$ gcloud sql instances create codelab-instance --region=us-east1
پس از اینکه نمونه Cloud SQL خود را با موفقیت ایجاد کردید، یک پایگاه داده جدید در نمونه خود به نام registrants
ایجاد کنید.
$ gcloud sql databases create registrants --instance codelab-instance
اکنون نمونه Cloud SQL و تنظیم پایگاه داده را برای برنامه خود تکمیل کرده اید.
5. یک برنامه Spring Boot را راه اندازی کنید
اکنون آماده شروع نوشتن برنامه هستیم. مراحل بعدی با استفاده از Cloud Shell که در مراحل راهاندازی توضیح داده شده است ادامه مییابد.
ابتدا از Initializr برای تولید کد داربست پروژه استفاده می کنیم. در پنجره Cloud Shell خود، اجرا کنید:
$ 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
این دستور یک راه اندازی اولیه پروژه Maven و همچنین کد داربست برای برنامه شما در registrations-codelab/
ایجاد می کند. بخشهای زیر ویرایشهای کد لازم برای تولید یک برنامه کاربردی را توضیح میدهند.
ویرایشگر کد پوسته ابری
ساده ترین راه برای شروع اصلاح و مشاهده کد در محیط Cloud Shell استفاده از ویرایشگر کد پوسته ابری داخلی است.
هنگامی که یک نمونه Cloud Shell را باز کردید، روی نماد Pencil کلیک کنید تا ویرایشگر کد باز شود. ویرایشگر باید به شما اجازه دهد که مستقیماً فایل های پروژه تولید شده توسط Initialzr را تغییر دهید.
6. پیکربندی پایگاه داده
ابتدا برنامه خود را پیکربندی کنید تا بتواند به پایگاه داده Cloud MySQL که راه اندازی کرده اید متصل شود. کتابخانههای Spring Cloud GCP یک راهانداز Cloud MySQL ارائه میکنند که وابستگیهای لازم را برای اتصال به یک نمونه ابری MySQL فراهم میکند.
وابستگی spring-cloud-gcp-starter-sql-mysql
به پروژه pom.xml اضافه کنید:
registers-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>
علاوه بر این، باید فایل پیکربندی application.properties
را برای توصیف پیکربندی پایگاه داده خود تغییر دهید. ویژگی های زیر را در فایل application.properties
خود کپی کنید.
نام اتصال نمونه به پایگاه داده خود را پیدا کنید:
$ gcloud sql instances describe codelab-instance \ --format 'value(connectionName)'
خروجی این در فایل application.properties
برای پیکربندی اطلاعات اتصال استفاده خواهد شد.
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
تنها ویژگی که باید تغییر دهید نام اتصال نمونه است. این مقدار باید به صورت یک مقدار جدا شده با دو نقطه با فرمت فرمت شود: YOUR_GCP_PROJECT_ID:REGION:DATABASE_INSTANCE_NAME
.
7. ایجاد محتوای ثابت
ابتدا، ما frontend را برای برنامه خود ایجاد می کنیم. این برنامه باید دارای فرمی باشد که به کسی اجازه می دهد افراد را ثبت کند و همچنین نمایی که همه ثبت نام کنندگان موفق را نشان می دهد.
برای صفحه اصلی، یک index.html
حاوی فرم ثبت نام ایجاد کنید.
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>
در مرحله بعد یک قالب Thymeleaf با نام registrants.html
برای نمایش کاربران ثبت نام شده ایجاد می کنیم. Thymeleaf یک چارچوب قالب است که ما از آن برای ساخت و ارائه HTML ایجاد شده به صورت پویا استفاده می کنیم. خواهید دید که قالب شبیه HTML است، با این تفاوت که دارای عناصر علامت گذاری اضافی برای مدیریت محتوای پویا است. این الگو یک پارامتر واحد به نام personsList
را می پذیرد که شامل همه ثبت نام کنندگانی است که از طریق برنامه ثبت نام کرده اند.
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>
در این مرحله، می توانید تأیید کنید که محتوای ثابت در حال ارائه است.
برنامه را با استفاده از Maven بسازید و اجرا کنید:
$ ./mvnw spring-boot:run
روی دکمه پیشنمایش در پنجره Cloud Shell کلیک کنید و بررسی کنید که صفحه اصلی را در حال ارائه میبینید. هیچ یک از عملکردهای UI کار نخواهد کرد زیرا ما یک کنترلر وب را از دست داده ایم. این در مرحله بعد اضافه خواهد شد.
پس از پیش نمایش برنامه، CTRL+C
را فشار دهید تا برنامه خاتمه یابد.
8. ارسال ثبت نام کنندگان به یک میخانه/موضوع فرعی
در این مرحله، ویژگی را پیاده سازی می کنیم که ثبت نام کنندگان از طریق فرم وب در یک موضوع Cloud Pub/Sub منتشر می شوند.
کلاس های داده را اضافه کنید
اول، ما چند کلاس داده Kotlin ایجاد خواهیم کرد. اینها نهادهای JPA ما خواهند بود و همچنین به عنوان نماینده میانی ما از ثبت نام کنندگان ارسال شده از طریق فرم عمل می کنند.
در بسته آزمایشی، دو فایل جدید اضافه کنید: یک کلاس Person
و یک Spring Data PersonRepository
. این دو کلاس به ما این امکان را می دهند که به راحتی ورودی های ثبت نام را از پایگاه داده MySQL خود با استفاده از 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>
کنترلر وب را اضافه کنید
در مرحله بعد، ما یک کلاس Controller ایجاد می کنیم که ثبت نام کنندگان را از فرم پردازش می کند و اطلاعات را به موضوع Cloud Pub/Sub که قبلا ایجاد کرده اید ارسال می کند. این کنترلر دو نقطه پایانی ایجاد می کند:
-
/registerPerson
: نقطه پایانی POST که در آن اطلاعات ثبتکننده ارسال میشود و سپس به موضوع Pub/Sub ارسال میشود. در تابعregisterPerson(..)
، اطلاعات ثبتکننده با استفاده ازPubSubTemplate
به مبحث Pub/Sub فرستاده میشود، یک کلاس راحتی از ادغامهای Spring Cloud GCP Pub/Sub که کد دیگ بخار مورد نیاز برای شروع تعامل با Cloud Pub/Sub را به حداقل میرساند. -
/registrants
: تمام ثبت نام کنندگانی که با موفقیت در پایگاه داده ثبت نام کرده اند را نمایش می دهد. این اطلاعات از نمونه MySQL با استفاده از مخزن Spring Data که در مرحله قبل ایجاد کردیم، بازیابی می شود.
کلاس Controller زیر را در بسته دمو ایجاد کنید:
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))
}
}
کنترل کننده اطلاعات ثبت نام کننده ارسال شده از طریق فرم وب را می خواند و سپس اطلاعات را در موضوع Pub/Sub منتشر می کند.
افزودن JSON Object Mapper Bean
ممکن است در Controller متوجه شده باشید که ما یک شی Person
را در موضوع Pub/Sub منتشر می کنیم و نه یک رشته. این امکان پذیر است زیرا ما از پشتیبانی Spring Cloud GCP برای بارهای سفارشی JSON برای ارسال به موضوعات استفاده می کنیم - کتابخانه ها به شما امکان می دهند اشیاء را به JSON سریال کنید ، بارهای JSON را به یک موضوع ارسال کنید، و پس از دریافت بار، آن را از فهرست خارج کنید.
برای استفاده از این ویژگی، باید یک ObjectMapper
bean را به زمینه برنامه شما اضافه کنیم. هنگامی که برنامه شما پیام می فرستد و دریافت می کند، از این لوبیا ObjectMapper
برای سریال کردن اشیا به JSON و از JSON استفاده می شود. در کلاس DemoApplication.kt
، لوبیا بهار JacksonPubSubMessageConverter
را اضافه کنید:
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)
}
در این مرحله، میتوانید با اجرای:
$ ./mvnw spring-boot:run
از فرم وب در صفحه اصلی، برنامه اکنون اطلاعات را به موضوع Pub/Sub که ایجاد کرده اید ارسال می کند. با این حال، هنوز هیچ کار مفیدی انجام نمی دهد زیرا ما هنوز باید از آن موضوع Pub/Sub مطالعه کنیم! این در مرحله بعدی انجام می شود.
9. خواندن ثبت نام کنندگان از میخانه / موضوع فرعی
در مرحله آخر، اطلاعات ثبتکننده را از مبحث Pub/Sub پردازش میکنیم و اطلاعات را در پایگاه داده Cloud MySQL حفظ میکنیم. این برنامه را تکمیل می کند و به شما امکان می دهد ثبت نام کنندگان جدید را از طریق فرم ارسال کنید و همه کاربران ثبت نام شده را از طریق نقطه پایانی /registrants
مشاهده کنید.
این برنامه از یکپارچگی بهار بهره می برد که انتزاعات راحت زیادی را برای پرداختن به پیام ارائه می دهد. ما یک PubSubInboundChannelAdapter
اضافه می کنیم تا بتوانیم پیام ها را از موضوع Pub/Sub بخوانیم و آنها را برای پردازش بیشتر در pubsubInputChannel
قرار دهیم. سپس تابع messageReceiver
را با استفاده از @ServiceActivator
پیکربندی میکنیم تا با پیامهایی که به 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)
}
در این مرحله، تنظیمات برنامه را تکمیل کرده اید. برای تأیید اینکه برنامه به درستی کار می کند، اجرا کنید:
$ ./mvnw spring-boot:run
دوباره روی دکمه Preview کلیک کنید و با پر کردن فرم و ارسال، ثبت نام کاربر را امتحان کنید.
روی پیوند افراد ثبت نام شده کلیک کنید تا تأیید کنید که ثبت نام کننده جدید در جدول ظاهر می شود.
تبریک می گویم، شما اکنون تمام شده اید! برنامه را با فشار دادن CTRL+C
در پنجره ترمینال خاتمه دهید.
10. پاکسازی
برای تمیز کردن محیط خود، باید موضوع Pub/Sub و نمونه Cloud MySQL را که ایجاد کرده اید حذف کنید.
حذف نمونه Cloud MySQL
$ gcloud sql instances delete codelab-instance
حذف منابع Pub/Sub
$ gcloud pubsub subscriptions delete registrations-sub $ gcloud pubsub topics delete registrations
11. تبریک می گویم!
شما اکنون نوشتن یک برنامه Spring Kotlin را تکمیل کرده اید که با Cloud Pub/Sub و Cloud SQL (MySQL) ادغام می شود.
بیشتر بدانید
- پروژه Spring on GCP: http://cloud.spring.io/spring-cloud-gcp/
- Spring در مخزن GCP GitHub: https://github.com/GoogleCloudPlatform/spring-cloud-gcp
- جاوا در Google Cloud Platform: https://cloud.google.com/java/
- نمونه برنامه های Kotlin با استفاده از GCP: https://github.com/GoogleCloudPlatform/spring-cloud-gcp/tree/master/spring-cloud-gcp-kotlin-samples
مجوز
این اثر تحت مجوز Creative Commons Attribution 2.0 Generic مجوز دارد.