对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

将MongoDB与 Quarkus 集成

在本指南中,您可以学习;了解如何创建Java REST API ,该 API 使用 Quarkus 作为 Web框架和 Eclipse JNoSQL 来访问权限MongoDB。Quarkus 是一个开源Java框架,专为云原生微服务和无服务器开发而设计。Eclipse JNOSQL 实现 Jakarta NoSQL 和 Jakarta Data 规范,以简化Java应用程序与 NoSQL 数据库的集成。

本教程中的应用程序由以下各层组成:

  • 数据库层:MongoDB提供数据存储和检索。

  • 应用程序层:Quarkus 处理HTTP请求、路由和依赖项注入。

  • 数据访问权限层:JNoSQL 提供MongoDB文档映射和存储库模式。

本教程使用 Quarkus JNoSQL 扩展访问权限MongoDB,该扩展为 NoSQL 数据库提供了统一的API ,并允许您通过熟悉的Java模式和注解来使用MongoDB 。因此,您可以使用MongoDB和 Quarkus 以最少的配置开发轻量级应用程序。

通过将MongoDB与 Quarkus 集成,您可以利用 Quarkus 的快速初创企业时间和高效的资源利用以及 MongoDB 灵活的文档模型。这种组合支持需要类型安全、可扩展性和快速开发周期的应用程序。您可以使用MongoDB和 Quarkus 来创建实际应用程序,例如微服务、云原生 API 或需要高性能和低资源消耗的系统。

本教程向您展示如何构建使用MongoDB和 Quarkus 的REST API 。该应用程序访问示例餐厅数据,查询数据,并通过 RESTful 终结点返回结果。本教程还包括连接到MongoDB Atlas上托管的MongoDB 集群的说明。

提示

如果您希望使用 Java 驱动程序而不使用 Quarkus 连接到 MongoDB,请参阅Java 驱动程序入门教程。

按照本节中的步骤安装项目依赖项,创建Atlas集群,并设立应用程序结构。

1

要创建快速入门应用程序,请在开发环境中安装以下软件:

先决条件
注意

安装 JDK 版本 21 或更高版本。

使用 3.8.1 或更高版本。

此命令行界面允许您从终端创建和托管 Quarkus 项目。
重要提示:本教程使用版本 3.30.6,较新版本可能会导致错误。按照您的操作系统,遵循相应的安装说明安装特定版本。

代码编辑器

使用您选择的代码编辑器。

终端应用和shell

对于 MacOS 用户,请使用终端或类似应用。对于Windows用户,请使用 PowerShell 或命令提示符。

2

MongoDB Atlas是一项完全托管云数据库服务,用于托管MongoDB部署。如果您没有MongoDB 部署,可以通过完成MongoDB入门教程来免费创建MongoDB 集群。MongoDB入门教程还演示了如何将示例数据集加载到集群中,包括本教程中使用的 sample_restaurants数据库。

要连接到MongoDB 集群,必须使用连接字符串。要学习;了解如何检索连接字符串,请参阅MongoDB入门教程的添加连接字符串部分。

重要

将连接string保存在安全位置。

3

从终端运行以下命令,创建一个名为 quarkus-quickstart 的新 Quarkus项目,为 REST 终结点配置 Quarkus JNoSQL Extension for MongoDB和JSON序列化:

quarkus create app quarkus-quickstart --extensions=jnosql-mongodb,resteasy-jackson

然后,通过运行以下命令导航到项目目录:

cd quarkus-quickstart
4

导航到 src/main/resources/application.properties文件并添加以下配置属性:

jnosql.document.database=sample_restaurantsquarkus.mongodb.connection-string=<connection string>

此代码将配置与MongoDB 集群中 sample_restaurants数据库的连接。将 <connection string> 占位符替换为在上一步中保存的连接字符串。

5

Quarkus项目模板包含一些示例文件,您可以在本教程中删除这些文件。要删除这些不需要的文件,请选择与操作系统对应的标签页,然后从 quarkus-quickstart目录运行以下命令:

rm src/main/java/org/acme/Car.javarm src/main/java/org/acme/Garage.javarm src/test/java/org/acme/GarageTest.javarm src/main/java/org/acme/GreetingResource.javarm src/test/java/org/acme/GreetingResourceIT.javarm src/test/java/org/acme/GreetingResourceTest.java

设置项目结构和依赖项后,请按照本节中的步骤创建数据模型、存储库类和 REST 终结点。

1

在 src/main/java/org/acme目录中创建名为 Restaurant.java 的文件,然后粘贴以下代码:

quarkus-quickstart/src/main/java/org/acme/Restaurant.java

package org.acme; import jakarta.nosql.Column;import jakarta.nosql.Entity;import jakarta.nosql.Id; /** * Represents a restaurant entity from the sample_restaurants database . * This class is used as an entity in the MongoDB database. */@Entity("restaurants")public class Restaurant { @Id private String id; @Column private String name; @Column private String borough; @Column private String cuisine; // Default constructor required by JNoSQL public Restaurant() {} // Constructor public Restaurant(String id, String name, String borough,String cuisine) { this.id = id; this.name = name; this.borough = borough; this.cuisine = cuisine; } // Getters and setters public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getBorough() { return borough; } public void setBorough(String borough) { this.borough = borough; } public String getCuisine() { return cuisine; } public void setCuisine(String cuisine) { this.cuisine = cuisine; }}

此文件定义了 Restaurant 实体类,它映射到 sample_restaurants.restaurants集合中的文档。@Entity 注释将此类标记为 JNoSQL 实体,字段注释将Java属性映射到文档字段。

2

在 src/main/java/org/acme目录中创建名为 RestaurantRepository.java 的文件,然后粘贴以下代码:

quarkus-quickstart/src/main/java/org/acme/RestaurantRepository.java

package org.acme; import jakarta.data.repository.Repository;import org.eclipse.jnosql.mapping.NoSQLRepository; import java.util.List; /** * Interface for managing restaurant data. * * It uses the Jakarta Data Specification capabilities. * */@Repositorypublic interface RestaurantRepository extends NoSQLRepository<Restaurant, String> { List<Restaurant> findByBorough(String borough); List<Restaurant> findByCuisine(String cuisine);}

该存储库库类提供了访问MongoDB中餐厅数据的方法。它定义了自定义 findByBorough() 和 findByCuisine()查询方法,您还可以使用 RestaurantRepository实例访问权限内置的创建、读取、更新和删除方法。

3

在 src/main/java/org/acme目录中,创建名为 RestaurantResource.java 的文件并粘贴以下代码:

quarkus-quickstart/src/main/java/org/acme/RestaurantResource.java

package org.acme; import jakarta.inject.Inject;import jakarta.ws.rs.*;import jakarta.ws.rs.core.MediaType;import jakarta.ws.rs.core.Response;import java.util.List; /** * REST API controller for restaurant operations. * Provides endpoints for retrieving restaurant data from MongoDB. */@Path("/restaurants")@Produces(MediaType.APPLICATION_JSON)@Consumes(MediaType.APPLICATION_JSON)public class RestaurantResource { @Inject RestaurantRepository restaurantRepository; /** * Retrieves all restaurants from the database. * * @return List of all restaurants */ @GET public Response getAllRestaurants() { try { List<Restaurant> restaurants = restaurantRepository.findAll().toList(); System.out.println("Found " + restaurants.size() + " restaurants"); return Response.ok(restaurants).build(); } catch (Exception e) { e.printStackTrace(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Error retrieving restaurants: " + e.getMessage()) .build(); } } /** * Retrieves filtered restaurants in Queens that contain "Moon" in the name. * * @return List of filtered restaurants */ @GET @Path("/browse") public Response getFilteredRestaurants() { try { // Temporarily use findAll() to test basic connectivity List<Restaurant> allRestaurants = restaurantRepository.findAll().toList(); System.out.println("Total restaurants found: " + allRestaurants.size()); // Filter for Queens restaurants that also have "Moon" in the name List<Restaurant> queensRestaurants = allRestaurants.stream() .filter(restaurant -> "Queens".equals(restaurant.getBorough()) && restaurant.getName() != null && restaurant.getName().toLowerCase().contains("moon")) .toList(); System.out.println("Queens restaurants found: " + queensRestaurants.size()); return Response.ok(queensRestaurants).build(); } catch (Exception e) { e.printStackTrace(); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Error retrieving filtered restaurants: " + e.getMessage()) .build(); } } /** * Retrieves restaurants by cuisine type. * * @param cuisine The cuisine type to filter for * @return List of restaurants that have the specified cuisine */ @GET @Path("/cuisine/{cuisine}") public Response getRestaurantsByCuisine(@PathParam("cuisine") String cuisine) { try { List<Restaurant> restaurants = restaurantRepository.findByCuisine(cuisine); return Response.ok(restaurants).build(); } catch (Exception e) { return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity("Error retrieving restaurants by cuisine: " + e.getMessage()) .build(); } }}

此 REST资源类定义以下HTTP终结点:

  • GET /restaurants/:检索 restaurants集合中的所有文档

  • GET /restaurants/browse:检索代表皇后区名称中包含 "Moon" 的餐厅的文档,执行不区分大小写的查询

  • GET /restaurants/cuisine/{cuisine}:检索代表提供指定 cuisine 值的餐厅的文档

4

在 src/test/java/org/acme目录中,创建名为 RestaurantRepositoryTest.java 的文件并粘贴以下代码:

quarkus-quickstart/src/test/java/org/acme/RestaurantRepositoryTest.java

package org.acme; import io.quarkus.test.junit.QuarkusTest;import jakarta.inject.Inject;import org.junit.jupiter.api.DisplayName;import org.junit.jupiter.api.Test; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; /** * RestaurantRepositoryTest is a test class for testing the RestaurantRepository operations. * * It uses the Quarkus Test framework to test the restaurant data access. */@QuarkusTestpublic class RestaurantRepositoryTest { @Inject RestaurantRepository restaurantRepository; @Test @DisplayName("Should retrieve restaurants from the database") public void testRetrieveRestaurants() { // Test repository injection and MongoDB connection assertThat(restaurantRepository).isNotNull(); } @Test @DisplayName("Should find restaurants by borough") public void testFindRestaurantsByBorough() { // Test that the method exists and returns data List<Restaurant> restaurants = restaurantRepository.findByBorough("Queens"); assertThat(restaurants).isNotNull(); }}

该文件使用 Quarkus 的测试框架进行集成测试。该代码定义了以下方法来测试MongoDB连接:

  • testRetrieveRestaurants():验证您的 RestaurantRepository 类是否可以访问MongoDB

  • testFindRestaurantsByBorough():验证 findByBorough() 方法是否检索MongoDB数据

最后,按照本部分中的步骤运行REST API并使用 curl 命令测试终结点。

1

首先,从项目目录运行以下命令来运行测试套件:

./mvnw test

此命令运行 RestaurantRepositoryTest 类并验证您的应用程序是否可以访问权限MongoDB数据。如果成功,命令输出将包含以下信息:

[INFO] Results:[INFO][INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0[INFO][INFO] ------------------------------------------------------------------------[INFO] BUILD SUCCESS[INFO] ------------------------------------------------------------------------[INFO] Total time: ... s[INFO] Finished at: ...[INFO] ------------------------------------------------------------------------
2

在项目目录中,运行以下命令以编译并在开发模式下启动应用程序:

./mvnw quarkus:dev
3

在单独的终端窗口中,运行以下 curl 命令以测试 REST 终结点。每个终结点返回包含 sample_restaurants.restaurants集合中的餐厅信息的JSON数据。如果成功,您的命令将返回与示例输出类似的数据。

  1. 检索所有餐厅。

    curl http://localhost:8080/restaurants/
  2. 检索名称中包含 "Moon" 的皇后区餐厅。

    curl http://localhost:8080/restaurants/browse
  3. 按菜系类型检索餐厅。

    以下命令会查询 cuisine 值为 "Czech" 的餐厅,但您可以将此参数替换为任何菜系:

    curl http://localhost:8080/restaurants/cuisine/Czech

恭喜您完成 Quarkus 快速入门教程!完成这些步骤后,您就拥有一个Java Quarkus REST API ,它可以连接到MongoDB 部署、对示例餐厅数据运行查询,并通过HTTP终结点公开结果,您可以使用 curl 命令测试这些终结点。

要学习有关 Quarkus、JNoSQL 和 MongoDB 的更多信息,请参阅以下资源: