1. Einführung
Für Spring Framework 5.0 wurde spezielle Kotlin-Unterstützung hinzugefügt, um Kotlin-Entwicklern die Verwendung von Spring zu erleichtern. Diese Änderungen führten dazu, dass die von Spring Cloud GCP bereitgestellten Google Cloud-Integrationen auch in Kotlin reibungslos funktionieren. In diesem Codelab erfahren Sie, wie einfach es ist, Google Cloud-Dienste in Ihren Kotlin-Anwendungen zu verwenden.
In diesem Codelab erfahren Sie, wie Sie eine einfache Registrierungsanwendung in Kotlin einrichten und so die Verwendung von GCP-Diensten wie Cloud Pub/Sub und Cloud SQL demonstriert.
Aufgaben
In diesem Codelab richten Sie eine Kotlin Spring Boot-Anwendung ein, die Domaininhaberinformationen annimmt, in einem Cloud Pub/Sub-Thema veröffentlicht und in einer Cloud MySQL-Datenbank speichert.
Lerninhalte
Hier erfahren Sie, wie Sie Google Cloud-Dienste in Ihre Kotlin Spring-Anwendung einbinden.
Voraussetzungen
- Google Cloud Platform-Projekt
- Browser wie Chrome oder Firefox
Wie möchten Sie diese Anleitung nutzen?
<ph type="x-smartling-placeholder">Wie würden Sie Ihre Erfahrung mit der Erstellung von HTML/CSS-Web-Apps bewerten?
<ph type="x-smartling-placeholder">Wie würden Sie Ihre Erfahrungen im Umgang mit Google Cloud Platform-Diensten bewerten?
<ph type="x-smartling-placeholder">2. Einrichtung und Anforderungen
Umgebung für das selbstbestimmte Lernen einrichten
- Melden Sie sich in der Cloud Console an und erstellen Sie ein neues Projekt oder verwenden Sie ein vorhandenes Projekt. Wenn Sie noch kein Gmail- oder G Suite-Konto haben, müssen Sie eines erstellen.
Notieren Sie sich die Projekt-ID, also den projektübergreifend nur einmal vorkommenden Namen eines Google Cloud-Projekts. Der oben angegebene Name ist bereits vergeben und kann leider nicht mehr verwendet werden. Sie wird in diesem Codelab später als PROJECT_ID
bezeichnet.
- Als Nächstes müssen Sie in der Cloud Console die Abrechnung aktivieren, um Google Cloud-Ressourcen nutzen zu können.
Dieses Codelab sollte ohne großen Aufwand betrieben werden. Folgen Sie der Anleitung im Abschnitt „Bereinigen“, . Hier erfahren Sie, wie Sie Ressourcen herunterfahren, damit Ihnen über dieses Tutorial hinaus keine Kosten entstehen. Neue Google Cloud-Nutzer können an einem kostenlosen Testzeitraum mit 300$Guthaben teilnehmen.
Google Cloud Shell
Sie können Google Cloud zwar von Ihrem Laptop aus aus der Ferne bedienen, in diesem Codelab verwenden wir jedoch Google Cloud Shell, eine Befehlszeilenumgebung, die in der Cloud ausgeführt wird.
Cloud Shell aktivieren
- Klicken Sie in der Cloud Console auf Cloud Shell aktivieren .
Wenn Sie Cloud Shell zum ersten Mal verwenden, wird ein Zwischenbildschirm (below the fold) angezeigt, in dem beschrieben wird, worum es sich dabei handelt. Klicken Sie in diesem Fall auf Weiter. Der Chat wird nie wieder angezeigt. So sieht dieser einmalige Bildschirm aus:
Die Bereitstellung und Verbindung mit Cloud Shell dauert nur einen Moment.
Diese virtuelle Maschine verfügt über sämtliche Entwicklertools, die Sie benötigen. Es bietet ein Basisverzeichnis mit 5 GB nichtflüchtigem Speicher und wird in Google Cloud ausgeführt. Dadurch werden die Netzwerkleistung und die Authentifizierung erheblich verbessert. Viele, wenn nicht sogar alle Arbeiten in diesem Codelab können Sie ganz einfach mit einem Browser oder Ihrem Chromebook erledigen.
Sobald Sie mit Cloud Shell verbunden sind, sollten Sie sehen, dass Sie bereits authentifiziert sind und dass das Projekt bereits auf Ihre Projekt-ID eingestellt ist.
- Führen Sie in Cloud Shell den folgenden Befehl aus, um zu prüfen, ob Sie authentifiziert sind:
gcloud auth list
Befehlsausgabe
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
gcloud config list project
Befehlsausgabe
[core] project = <PROJECT_ID>
Ist dies nicht der Fall, können Sie die Einstellung mit diesem Befehl vornehmen:
gcloud config set project <PROJECT_ID>
Befehlsausgabe
Updated property [core/project].
3. Pub/Sub-Ressourcen bereitstellen
Zuerst müssen Sie ein Cloud Pub/Sub-Thema und ein Abo einrichten. In dieser Anwendung veröffentlichen wir Registrierungsinformationen zu einem Pub/Sub-Thema. werden die Informationen aus diesem Thema gelesen und in einer Datenbank gespeichert.
In dieser Anleitung verwenden wir Cloud Shell, um die Ressourcen bereitzustellen. Pub/Sub-Ressourcen können auch über den Bereich „Cloud Pub/Sub“ in der Google Cloud Console konfiguriert werden.
Aktivieren Sie im Cloud Shell-Terminal zuerst die Pub/Sub API.
$ gcloud services enable pubsub.googleapis.com
Als Nächstes erstellen wir ein Pub/Sub-Thema mit dem Namen registrations
für diese Anwendung. Die über die Anwendung eingereichten Registrierungsinformationen werden unter diesem Thema veröffentlicht.
$ gcloud pubsub topics create registrations
Erstellen Sie abschließend ein Abo für das Thema. Mit einem Pub/Sub-Abo können Sie Nachrichten von einem Thema empfangen.
$ gcloud pubsub subscriptions create registrations-sub --topic=registrations
Sie haben jetzt ein Cloud Pub/Sub-Thema und -Abo für Ihre Anwendung erstellt.
4. Cloud SQL-Instanz und -Datenbank erstellen
Für unsere Beispielanwendung müssen wir außerdem eine Datenbankinstanz einrichten, in der die Daten des Domaininhabers gespeichert werden. Bei diesem Schritt werden Cloud SQL-Ressourcen auch vom Cloud Shell-Terminal bereitgestellt. Sie können Ihre Cloud SQL-Instanzen auch über die Google Cloud Console aufrufen und konfigurieren.
Aktivieren Sie zuerst die Cloud SQL Admin API.
$ gcloud services enable sqladmin.googleapis.com
Als Nächstes stellen wir eine Cloud SQL-Instanz (MySQL) bereit. Dieser Befehl kann einige Zeit dauern.
$ gcloud sql instances create codelab-instance --region=us-east1
Nachdem Sie die Cloud SQL-Instanz erfolgreich erstellt haben, erstellen Sie darin eine neue Datenbank mit dem Namen registrants
.
$ gcloud sql databases create registrants --instance codelab-instance
Sie haben jetzt die Einrichtung der Cloud SQL-Instanz und der Datenbank für Ihre Anwendung abgeschlossen.
5. Spring Boot-Anwendung initialisieren
Jetzt können wir mit dem Schreiben der Anwendung beginnen. Bei den nächsten Schritten wird weiterhin die in den Einrichtungsschritten beschriebene Cloud Shell verwendet.
Zuerst verwenden wir Initializr, um den Scaffolding-Code für das Projekt zu generieren. Führen Sie im Cloud Shell-Fenster folgenden Befehl aus:
$ 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
Dieser Befehl generiert eine erste Maven-Projekteinrichtung sowie einen Gerüstcode für Ihre Anwendung im Verzeichnis registrations-codelab/
. In den folgenden Abschnitten werden Codebearbeitungen beschrieben, die zum Erstellen einer funktionierenden Anwendung erforderlich sind.
Cloud Shell-Code-Editor
Am einfachsten lässt sich Code in der Cloud Shell-Umgebung mit dem integrierten Cloud Shell-Code-Editor ändern und aufrufen.
Klicken Sie in einer Cloud Shell-Instanz auf das Stiftsymbol, um den Code-Editor zu öffnen. Im Editor sollten Sie die von Initialzr erstellten Projektdateien direkt bearbeiten können.
6. Datenbankkonfiguration
Konfigurieren Sie zuerst Ihre Anwendung so, dass sie eine Verbindung zur von Ihnen eingerichteten Cloud MySQL-Datenbank herstellen kann. Die Spring Cloud GCP-Bibliotheken bieten einen Cloud MySQL-Starter, der die erforderlichen Abhängigkeiten für die Verbindung mit einer Cloud MySQL-Instanz bereitstellt.
Fügen Sie die Abhängigkeit spring-cloud-gcp-starter-sql-mysql
zum Projekt pom.xml hinzu:
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>
Außerdem müssen Sie die Konfigurationsdatei application.properties
ändern, um Ihre Datenbankkonfiguration zu beschreiben. Kopieren Sie die folgenden Attribute in die Datei application.properties
.
Suchen Sie den Namen der Instanzverbindung zu Ihrer Datenbank:
$ gcloud sql instances describe codelab-instance \ --format 'value(connectionName)'
Die Ausgabe wird in der Datei application.properties
verwendet, um die Verbindungsinformationen zu konfigurieren.
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
Das einzige Attribut, das Sie ändern müssen, ist der Name der Instanzverbindung. Dieser Wert muss als durch Doppelpunkte getrennter Wert im folgenden Format angegeben werden: YOUR_GCP_PROJECT_ID:REGION:DATABASE_INSTANCE_NAME
.
7. Statische Inhalte erstellen
Zuerst erstellen wir das Frontend für die Anwendung. Die Bewerbung sollte ein Formular enthalten, über das Einzelpersonen registriert werden können, sowie eine Ansicht, in der alle erfolgreichen Teilnehmer angezeigt werden.
Erstelle für die Startseite eine index.html
, die das Registrierungsformular enthält.
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>
Als Nächstes erstellen wir eine Thymeleaf-Vorlage mit dem Namen registrants.html
, um die registrierten Nutzer anzuzeigen. Thymeleaf ist ein Vorlagen-Framework, mit dem wir dynamisch erstellten HTML-Code konstruieren und bereitstellen. Sie sehen, dass die Vorlage wie HTML aussieht. Der einzige Unterschied besteht darin, dass sie einige zusätzliche Markdown-Elemente zur Verarbeitung dynamischer Inhalte enthält. Diese Vorlage akzeptiert einen einzelnen Parameter namens personsList
, der alle Domaininhaber enthält, die über die Anwendung registriert wurden.
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>
An dieser Stelle können Sie überprüfen, ob der statische Inhalt bereitgestellt wird.
Erstellen Sie die Anwendung mit Maven und führen Sie sie aus:
$ ./mvnw spring-boot:run
Klicken Sie im Cloud Shell-Fenster auf die Vorschauschaltfläche und prüfen Sie, ob die gerenderte Startseite angezeigt wird. Die Funktionen auf der Benutzeroberfläche sind jedoch nicht verfügbar, da ein Web-Controller fehlt. Diese wird im nächsten Schritt hinzugefügt.
Nachdem Sie eine Vorschau der Anwendung angezeigt haben, drücken Sie CTRL+C
, um sie zu beenden.
8. Domaininhaber an ein Pub/Sub-Thema senden
In diesem Schritt implementieren wir die Funktion, mit der über das Webformular eingereichte Domaininhaber in einem Cloud Pub/Sub-Thema veröffentlicht werden.
Datenklassen hinzufügen
Zuerst werden wir einige Kotlin-Datenklassen erstellen: Diese sind unsere JPA-Rechtssubjekte und fungieren zugleich als Vermittler*in für die über das Formular eingereichten Domaininhaber.
Fügen Sie im Demopaket zwei neue Dateien hinzu: eine Person
-Klasse und eine Spring Data-PersonRepository
. Mit diesen beiden Klassen können wir Registrierungseinträge mithilfe von Spring Data JPA einfach speichern und aus unserer MySQL-Datenbank abrufen.
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>
Web Controller hinzufügen
Als Nächstes erstellen wir eine Controller-Klasse, die Domaininhaber aus dem Formular verarbeitet und die Informationen an das zuvor erstellte Cloud Pub/Sub-Thema sendet. Dieser Controller erstellt zwei Endpunkte:
/registerPerson
: Der POST-Endpunkt, an dem Informationen des Domaininhabers gesendet und dann an das Pub/Sub-Thema gesendet werden. In der FunktionregisterPerson(..)
werden Informationen des Domaininhabers mithilfe vonPubSubTemplate
an das Pub/Sub-Thema gesendet. Dies ist eine Convenience-Klasse aus den Pub/Sub-Integrationen von Spring Cloud GCP, die den für die Interaktion mit Cloud Pub/Sub erforderlichen Standardcode minimiert./registrants
: Zeigt alle Domaininhaber an, die erfolgreich in der Datenbank registriert wurden. Diese Informationen werden aus der MySQL-Instanz mithilfe des Spring Data-Repositorys abgerufen, das wir im vorherigen Schritt erstellt haben.
Erstellen Sie die folgende Controller-Klasse im Demopaket:
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))
}
}
Der Datenverantwortliche liest die über das Webformular eingereichten Informationen über den Domaininhaber und veröffentlicht sie im Pub/Sub-Thema.
JSON Object Mapper-Bean hinzufügen
Sie haben vielleicht bemerkt, dass im Controller ein Person
-Objekt im Pub/Sub-Thema und nicht als String veröffentlicht wird. Dies ist möglich, weil wir die Spring Cloud GCP-Unterstützung für benutzerdefinierte JSON-Nutzlasten nutzen, die an Themen gesendet werden. Mit den Bibliotheken können Sie Objekte in JSON serialisieren, JSON-Nutzlasten an ein Thema senden und die Nutzlast beim Empfang deserialisieren.
Damit Sie diese Funktion nutzen können, müssen wir Ihrem Anwendungskontext eine ObjectMapper
-Bean hinzufügen. Diese ObjectMapper
-Bean wird verwendet, um Objekte zu und aus JSON zu serialisieren, wenn Ihre Anwendung Nachrichten sendet und empfängt. Fügen Sie in der Klasse DemoApplication.kt
die Spring-Bean JacksonPubSubMessageConverter
hinzu:
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)
}
Nun können Sie versuchen, die Anwendung noch einmal auszuführen, indem Sie Folgendes ausführen:
$ ./mvnw spring-boot:run
Die Anwendung sendet die Informationen aus dem Webformular auf der Hauptseite jetzt an das von Ihnen erstellte Pub/Sub-Thema. Es funktioniert jedoch noch nichts Nützliches, da wir noch aus diesem Pub/Sub-Thema lesen müssen. Dies wird im nächsten Schritt erledigt.
9. Domaininhaber aus dem Pub/Sub-Thema lesen
Im letzten Schritt werden die Informationen des Domaininhabers aus dem Pub/Sub-Thema verarbeitet und in der Cloud MySQL-Datenbank gespeichert. Damit wird der Antrag abgeschlossen und Sie können neue Domaininhaber über das Formular einreichen und alle registrierten Nutzer über den /registrants
-Endpunkt aufrufen.
Diese Anwendung nutzt Spring Integration, die viele praktische Abstraktionen für die Verarbeitung von Mitteilungen bietet. Wir fügen eine PubSubInboundChannelAdapter
hinzu, damit wir Nachrichten aus dem Pub/Sub-Thema lesen und zur weiteren Verarbeitung im pubsubInputChannel
ablegen können. Anschließend konfigurieren wir die messageReceiver
-Funktion mit @ServiceActivator
so, dass sie mit den auf pubsubInputChannel
eingehenden Nachrichten aufgerufen wird.
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)
}
Jetzt haben Sie die Einrichtung der Anwendung abgeschlossen. Führen Sie folgenden Befehl aus, um zu überprüfen, ob die Anwendung ordnungsgemäß funktioniert:
$ ./mvnw spring-boot:run
Klicken Sie erneut auf die Schaltfläche Vorschau und versuchen Sie, einen Nutzer zu registrieren, indem Sie das Formular ausfüllen und einreichen.
Klicken Sie auf den Link Registrierte Personen, um zu überprüfen, ob der neue Domaininhaber in der Tabelle angezeigt wird.
Herzlichen Glückwunsch, Sie sind jetzt fertig! Beenden Sie die Anwendung, indem Sie im Terminalfenster CTRL+C
drücken.
10. Bereinigen
Zum Bereinigen Ihrer Umgebung müssen Sie das von Ihnen erstellte Pub/Sub-Thema und die von Ihnen erstellte Cloud MySQL-Instanz löschen.
Cloud MySQL-Instanz löschen
$ gcloud sql instances delete codelab-instance
Pub/Sub-Ressourcen löschen
$ gcloud pubsub subscriptions delete registrations-sub $ gcloud pubsub topics delete registrations
11. Glückwunsch!
Sie haben nun eine Spring Kotlin-Anwendung geschrieben, die sich in Cloud Pub/Sub und Cloud SQL (MySQL) einbinden lässt.
Weitere Informationen
- Spring on GCP-Projekt: http://cloud.spring.io/spring-cloud-gcp/
- GitHub-Repository von Spring auf GCP: https://github.com/GoogleCloudPlatform/spring-cloud-gcp
- Java auf der Google Cloud Platform: https://cloud.google.com/java/
- Beispielanwendungen für Kotlin unter Verwendung der GCP: https://github.com/GoogleCloudPlatform/spring-cloud-gcp/tree/master/spring-cloud-gcp-kotlin-samples
Lizenz
Dieser Text ist mit einer Creative Commons Attribution 2.0 Generic License lizenziert.