1. 介绍
Google Cloud Datastore 是一种存储大量实时数据的高扩展性和坚固性的无模型文档型数据库,适合于实时应用。Spring Cloud 提供了轻量级应用的快速开发能力,通过完善的插件类层形成一个完整的应用开发组件体系。使用 Spring Cloud 3.x 可以完美场景化地集成 Google Cloud Datastore,轻松实现与 Google Cloud 环境的通信和数据操作。
2.数据库创建
创建数据库
Create a new Cloud Datastore database in your Google Cloud project if this has not already been done to allow Cloud Datastore to create and store entities.
https://console.cloud.google.com/datastore/databases
赋予项目中使用的用户访问权限
3. 原理
在 Spring Cloud 中,通过 Spring Data 层提供对 Google Cloud Datastore 的高度封装,使用者可以像操作本地数据一样,优雅场景化地操作 Datastore 中的文档。
- Spring Data 使用 Google Cloud Datastore 提供的应用端 API。
- 通过 DatastoreTemplate 调用基础 CRUD 操作方法,并支持自定义查询和处理。
- 在 Spring Cloud 中,使用配置文件就能实现 Google Cloud Datastore 的快速配置和部署。
4. 代码实现
1. 添加 Maven 依赖
在
pom.xml
文件中添加以下依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-cloud-gcp</artifactId>
<groupId>com.et</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-gcp-data-datastore-basic-sample</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-data-datastore</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
<!-- Test-related dependencies. -->
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
2. 配置 Google Cloud 凭资
在
application.properties
中配置实现 Datastore 访问:
spring.cloud.gcp.datastore.project-id=feisty-truth-447013-m7
spring.cloud.gcp.datastore.namespace=spring-demo
logging.level.root=WARN
spring.main.allow-circular-references=true
spring.cloud.gcp.credentials.location=file:/home/jxausea/cloudshell_open/feisty-truth-447013-m7-f5b59beab338.json
3. 定义文档实例
通过 JPA 类体与 Google Datastore 文档相对应:
/*
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.et;
import com.google.cloud.spring.data.datastore.core.mapping.Entity;
import org.springframework.data.annotation.Id;
/** This class represents a single book stored in Datastore. */
@Entity(name = "books")
public class Book {
@Id Long id;
private final String title;
private final String author;
private final 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
+ '}';
}
}
4. 创建数据操作代码
使用 Spring Data Repository 扩展 Datastore CRUD 功能:
/*
* Copyright 2017-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.et;
import com.google.cloud.spring.data.datastore.repository.DatastoreRepository;
import java.util.List;
/**
* This interface contains custom-defined query methods of which implementations are generated for
* you.
*/
public interface BookRepository extends DatastoreRepository<Book, Long> {
List<Book> findByAuthor(String author);
List<Book> findByYearGreaterThan(int year);
List<Book> findByAuthorAndYear(String author, int year);
}
5. 实现主逻辑
通过使用 Repository 实现主逻辑:
/*
* Copyright 2017-2022 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.et;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@RestController
public class BookController {
private final BookRepository bookRepository;
public BookController(BookRepository bookRepository) {
this.bookRepository = bookRepository;
}
@PostMapping("/saveBook")
public String saveBook(@RequestBody Book book) {
if (book == null) {
return "The book is invalid";
}
this.bookRepository.save(book);
return "success";
}
@GetMapping("/findAllBooks")
public String findAllBooks() {
Iterable<Book> books = this.bookRepository.findAll();
List<Book> bookList = new ArrayList<>();
books.forEach(bookList::add);
return books.toString();
}
@GetMapping("/findByAuthor")
public String findByAuthor(@RequestParam("author") String author) {
List<Book> books = this.bookRepository.findByAuthor(author);
return books.toString();
}
@GetMapping("/findByYearGreaterThan")
public String findByYearGreaterThan(@RequestParam("year") Optional<Integer> year) {
List<Book> books = this.bookRepository.findByYearGreaterThan(year.orElse(0));
return books.toString();
}
@GetMapping("/findByAuthorYear")
public String findByAuthorYear(
@RequestParam("author") String author,
@RequestParam("year") Optional<Integer> year) {
List<Book> books = this.bookRepository.findByAuthorAndYear(author, year.orElse(0));
return books.toString();
}
@DeleteMapping("/removeAllBooks")
public void removeAllBooks() {
this.bookRepository.deleteAll();
}
}
5. 测试
1. 启动应用
确保以上配置正确后,启动 Spring Boot 应用,使用 Postman 或 curl 调用程序。(因为网络原因,最好在cloud shell editor启动)
2. 提交请求例子
创建4本书
curl --location --request POST 'localhost:8080/saveBook' \
--header 'Content-Type: application/json' \
--data-raw '{
"title": "The Moon Is a Harsh Mistress",
"author": "Robert A. Heinlein",
"year": 1966
}'
curl --location --request POST 'localhost:8080/saveBook' \
--header 'Content-Type: application/json' \
--data-raw '{
"title": "Stranger in a Strange Land",
"author": "Robert A. Heinlein",
"year": 1961
}'
curl --location --request POST 'localhost:8080/saveBook' \
--header 'Content-Type: application/json' \
--data-raw '{
"title": "The Crack in Space",
"author": "Philip K. Dick",
"year": 1966
}'
curl --location --request POST 'localhost:8080/saveBook' \
--header 'Content-Type: application/json' \
--data-raw '{
"title": "Ubik",
"author": "Philip K. Dick",
"year": 1969
}'
查询全部的书
curl --location --request GET 'localhost:8080/findAllBooks'
根据作者查询
curl --location --request GET 'localhost:8080/findByAuthor?author=Robert A. Heinlein'
根据日期筛选
curl --location --request GET 'localhost:8080/findByYearGreaterThan?year=1960'
根据作者和日期筛选
curl --location --request GET 'localhost:8080/findByAuthorYear?author=Robert A. Heinlein&year=1966'
删除
curl --location --request DELETE 'localhost:8080/removeAllBooks'
6. 总结
通过上述步骤,我们完成了 Spring Cloud 3.x 集成 Google Datastore 的基础实现。这不仅仅是一个实现,还提供了一种解决方案,可以轻松处理任务的数据存储和查询需求。
7.引用