关于此 Codelab
1. 概览
Google Cloud Datastore 是一个 NoSQL 文档数据库,以可自动扩展、高性能和易于进行应用开发为设计宗旨。
学习内容
- 如何在 Spring Boot 中使用 Cloud Datastore 保存和检索 Java 对象
所需条件
您将如何使用本教程?
您如何评价自己在使用 Google Cloud Platform 服务方面的经验水平?
2. 设置和要求
自定进度的环境设置
如果您还没有 Google 帐号(Gmail 或 Google Apps),则必须创建一个。登录 Google Cloud Platform Console (console.cloud.google.com) 并创建一个新项目:
请记住项目 ID,它在所有 Google Cloud 项目中都是唯一名称(很抱歉,上述名称已被占用,您无法使用!)。它稍后将在此 Codelab 中被称为 PROJECT_ID
。
接下来,您需要在 Cloud Console 中启用结算功能,才能使用 Google Cloud 资源。
在此 Codelab 中运行仅花费几美元,但是如果您决定使用更多资源或继续让它们运行,费用可能更高(请参阅本文档末尾的“清理”部分)。
Google Cloud Platform 的新用户有资格获享 $300 免费试用。
激活 Google Cloud Shell
在 GCP 控制台中,点击右上角工具栏上的 Cloud Shell 图标:
然后点击“启动 Cloud Shell”:
配置和连接到环境应该只需要片刻时间:
这个虚拟机已加载了您需要的所有开发工具。它提供了一个永久性的 5GB 主目录,并且在 Google Cloud 上运行,从而大大增强了网络性能和身份验证功能。只需使用一个浏览器或 Google Chromebook 即可完成本实验中的大部分(甚至全部)工作。
在连接到 Cloud Shell 后,您应该会看到自己已通过身份验证,并且相关项目已设置为您的 PROJECT_ID。
在 Cloud Shell 中运行以下命令以确认您已通过身份验证:
gcloud auth list
命令输出
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
命令输出
[core] project = <PROJECT_ID>
如果不是上述结果,您可以使用以下命令进行设置:
gcloud config set project <PROJECT_ID>
命令输出
Updated property [core/project].
3. 初始化 Cloud Datastore
在 GCP Console 中,导航到菜单 -> Datastore(位于“存储”部分)。
如果您从未在当前项目中使用过 Datastore,则会看到“选择 Cloud Firestore 模式”屏幕。选择“Datastore 模式”选项。
然后,您会看到“选择数据的存储位置”屏幕。选择 us-east1 或任何其他地区位置,然后点击“创建数据库”:
4. 引导新的 Spring Boot Java 应用
在 CloudShell 环境中,使用以下命令初始化和启动新的 Spring Boot 应用:
$ curl https://start.spring.io/starter.tgz \ -d packaging=war \ -d dependencies=cloud-gcp \ -d baseDir=datastore-example \ -d bootVersion=2.1.1.RELEASE | tar -xzvf -
这将使用一个新的 Maven 项目、Maven 的 pom.xml
(一个 Maven 封装容器)和一个应用入口点来创建一个新的 datastore-example/
目录。
我们的应用将提供一个 CLI 供用户输入命令和查看结果。我们将创建一个类来表示图书,然后使用 Datastore Repository 将其保存到 Cloud Datastore。
我们还需要向 pom.xml
再添加一个必要的依赖项。
点击 Cloud Shell 菜单中的启动代码编辑器,打开网页代码编辑器。
编辑器加载后,修改 pom.xml
文件以添加 Spring Data Cloud Datastore Spring Boot 入门依赖项:
pom.xml
<project>
...
<dependencies>
...
<!-- Add GCP Datastore Starter -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-data-datastore</artifactId>
</dependency>
<!-- Add Spring Shell Starter -->
<dependency>
<groupId>org.springframework.shell</groupId>
<artifactId>spring-shell-starter</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
</dependencies>
</project>
5. 创建 Book 类
使用编辑器创建包含以下内容的 Book
类:
datastore-example/src/main/java/com/example/demo/Book.java
package com.example.demo;
import org.springframework.cloud.gcp.data.datastore.core.mapping.Entity;
import org.springframework.data.annotation.Id;
@Entity(name = "books")
public class Book {
@Id
Long id;
String title;
String author;
int year;
public Book(String title, String author, int year) {
this.title = title;
this.author = author;
this.year = year;
}
public long getId() {
return this.id;
}
@Override
public String toString() {
return "Book{" +
"id=" + this.id +
", title='" + this.title + '\'' +
", author='" + this.author + '\'' +
", year=" + this.year +
'}';
}
}
如您所见,这是一个简单的 POJO。该类带有 @Entity
注释,表示它可以存储在 Datastore 中并提供种类名称(将种类视为 SQL 数据库中的一个表,请参阅文档了解更多详情)。种类名称是可选的 - 如果省略它,系统将根据类名称生成种类名称。
请注意,我们已为 id
属性添加了 @Id
注释。这表示我们希望将此字段用作 Datastore 键的标识符部分。每个 Datastore 实体都需要一个标识符。支持的类型为 String
和 Long
。
我们会重写 toString
方法,使对象的字符串表示形式更具可读性;在我们将其打印出时,这非常有用。
别忘了保存文件!
6. 创建 BookRepository 接口
使用以下内容创建 BookRepository
类:
datastore-example/src/main/java/com/example/demo/BookRepository.java
package com.example.demo;
import java.util.List;
import org.springframework.cloud.gcp.data.datastore.repository.DatastoreRepository;
public interface BookRepository extends DatastoreRepository<Book, Long> {
List<Book> findByAuthor(String author);
List<Book> findByYearGreaterThan(int year);
List<Book> findByAuthorAndYear(String author, int year);
}
该接口扩展了 DatastoreRepository<Book, Long>
,其中 Book
是网域类,Long
是 Id
类型。我们在代码库中声明了三种查询方法,系统将在后台为其自动生成实现。
第一种是 findByAuthor
。就像您猜到的,此方法的实现会执行一个查询,该查询将在条件过滤器中使用用户提供的值来等效于作者字段。
findByYearGreaterThan
方法执行的查询会过滤大于用户提供的值的年份字段。
findByAuthorAndYear
执行的查询会查找作者字段和年份字段与用户提供的值匹配的实体。
7. 创建交互式 CLI 应用
打开主应用 DemoApplication
类,并按如下所示对其进行修改:
datastore-example/src/main/java/com/example/demo/DemoApplication.java
package com.example.demo;
import java.util.List;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
@ShellComponent
@SpringBootApplication
public class DemoApplication {
@Autowired
BookRepository bookRepository;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@ShellMethod("Saves a book to Cloud Datastore: save-book <title> <author> <year>")
public String saveBook(String title, String author, int year) {
Book savedBook = this.bookRepository.save(new Book(title, author, year));
return savedBook.toString();
}
@ShellMethod("Loads all books")
public String findAllBooks() {
Iterable<Book> books = this.bookRepository.findAll();
return Lists.newArrayList(books).toString();
}
@ShellMethod("Loads books by author: find-by-author <author>")
public String findByAuthor(String author) {
List<Book> books = this.bookRepository.findByAuthor(author);
return books.toString();
}
@ShellMethod("Loads books published after a given year: find-by-year-after <year>")
public String findByYearAfter(int year) {
List<Book> books = this.bookRepository.findByYearGreaterThan(year);
return books.toString();
}
@ShellMethod("Loads books by author and year: find-by-author-year <author> <year>")
public String findByAuthorYear(String author, int year) {
List<Book> books = this.bookRepository.findByAuthorAndYear(author, year);
return books.toString();
}
@ShellMethod("Removes all books")
public void removeAllBooks() {
this.bookRepository.deleteAll();
}
}
请注意我们是如何为类添加 @ShellComponent
注释的。这会告知 Spring 我们希望将此类用作 CLI 命令的来源。带 @ShellMethod
注释的方法将在应用中以 CLI 命令的形式公开。
在这里,我们使用在 BookRepository 接口中声明的方法:findByAuthor
、findByYearGreaterThan
和 findByAuthorAndYear
。此外,我们还使用三种内置方法:save
、findAll
和 deleteAll
。
我们来看一下 saveBook
方法。我们使用用户提供的标题、作者和年份值创建一个 Book
对象。如您所见,我们未提供 id
值,因此系统会在保存时自动为其分配 ID 字段。save
方法接受类型为 Book
的对象,并将其保存到 Cloud Datastore。它会返回一个 Book
对象,其中填充了所有字段,包括 id
字段。最后,我们返回此对象的字符串表示形式。
其余方法的工作方式类似:它们接受将参数传递给相应的代码库方法,并返回字符串化结果。
8. 运行应用
如需构建并启动应用,请在 Cloud Shell 中(通过 pom.xml
所在项目的 datastore-example/
根目录)执行此命令:
$ mvn spring-boot:run
构建阶段成功后,系统将显示 Spring 徽标并显示 Shell 提示:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.1.RELEASE) shell:>
现在,您可以对我们之前定义的命令进行实验。要查看命令列表,请使用 help 命令:
shell:> help ... find-all-books: Loads all books find-by-author: Loads books by author: find-by-author <author> find-by-author-year: Loads books by author and year: find-by-author-year <author> <year> find-by-year-after: Loads books published after a given year: find-by-year-after <year> remove-all-books: Removes all books save-book: Saves a book to Cloud Datastore: save-book <title> <author> <year>
请尝试以下操作:
- 使用
save-book
命令创建几本图书 - 使用
find-all-books
命令运行搜索 - 查找特定作者的图书 (
find-by-author <author>
) - 查找在特定年份之后出版的图书 (
find-by-year-after <year>
) - 按特定作者和年份查找图书 (
find-by-author-year <author> <year>
)
9. 使用网页界面查看 Datastore 中存储的内容
要查看实体在 Cloud Datastore 中的存储方式,请转到 GCP Console,然后导航到菜单 -> Datastore(位于“存储”部分)-> 实体(如有必要,请选择“[默认]”命名空间和“图书”种类)。
10. 清理
如需清理,请从应用 Shell 中使用适当命名的 remove-all-books
命令移除所有图书。
shell:> remove-all-books
要退出应用,请使用退出命令,然后按 Ctrl+C。
11. 恭喜!
在此 Codelab 中,您创建了一个交互式 CLI 应用,该应用可以在 Cloud Datastore 中存储和检索对象!
了解详情
- Cloud Datastore:https://cloud.google.com/datastore/
- Spring Shell:https://projects.spring.io/spring-shell/
- GCP 上的 Spring 项目:http://cloud.spring.io/spring-cloud-gcp/
- GCP GitHub 代码库上的 Spring:https://github.com/spring-cloud/spring-cloud-gcp
- Google Cloud Platform 上的 Java:https://cloud.google.com/java/
许可
此作品已获得 Creative Commons Attribution 2.0 通用许可授权。