Overview
在本指南中,您可以学习;了解如何创建Java REST API ,该 API 使用 Quarkus 作为 Web框架和 Eclipse JNoSQL 来访问权限MongoDB。Quarkus 是一个开源Java框架,专为云原生微服务和无服务器开发而设计。Eclipse JNOSQL 实现 Jakarta NoSQL 和 Jakarta Data 规范,以简化Java应用程序与 NoSQL 数据库的集成。
本教程中的应用程序由以下各层组成:
数据库层:MongoDB提供数据存储和检索。
应用程序层:Quarkus 处理HTTP请求、路由和依赖项注入。
数据访问权限层:JNoSQL 提供MongoDB文档映射和存储库模式。
为何将MongoDB与 Quarkus 结合使用?
本教程使用 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集群,并设立应用程序结构。
验证先决条件。
要创建快速入门应用程序,请在开发环境中安装以下软件:
先决条件 | 注意 |
|---|---|
安装 JDK 版本 21 或更高版本。 | |
使用 3.8.1 或更高版本。 | |
此命令行界面允许您从终端创建和托管 Quarkus 项目。 | |
代码编辑器 | 使用您选择的代码编辑器。 |
终端应用和shell | 对于 MacOS 用户,请使用终端或类似应用。对于Windows用户,请使用 PowerShell 或命令提示符。 |
配置数据库连接。
导航到 src/main/resources/application.properties文件并添加以下配置属性:
jnosql.document.database=sample_restaurantsquarkus.mongodb.connection-string=<connection string>此代码将配置与MongoDB 集群中 sample_restaurants数据库的连接。将 <connection string> 占位符替换为在上一步中保存的连接字符串。
清理模板文件。
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.javadel src/main/java/org/acme/Car.javadel src/main/java/org/acme/Garage.javadel src/test/java/org/acme/GarageTest.javadel src/main/java/org/acme/GreetingResource.javadel src/test/java/org/acme/GreetingResourceIT.javadel src/test/java/org/acme/GreetingResourceTest.java创建应用程序
设置项目结构和依赖项后,请按照本节中的步骤创建数据模型、存储库类和 REST 终结点。
创建 Restaurant 模型。
在 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属性映射到文档字段。
创建存储库库类。
在 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实例访问权限内置的创建、读取、更新和删除方法。
创建 REST资源类。
在 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值的餐厅的文档
创建一个测试类。
在 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类是否可以访问MongoDBtestFindRestaurantsByBorough():验证findByBorough()方法是否检索MongoDB数据
运行应用程序
最后,按照本部分中的步骤运行REST API并使用 curl 命令测试终结点。
运行测试。
首先,从项目目录运行以下命令来运行测试套件:
./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] ------------------------------------------------------------------------手动测试 REST 终结点。
在单独的终端窗口中,运行以下 curl 命令以测试 REST 终结点。每个终结点返回包含 sample_restaurants.restaurants集合中的餐厅信息的JSON数据。如果成功,您的命令将返回与示例输出类似的数据。
检索所有餐厅。
curl http://localhost:8080/restaurants/检索名称中包含
"Moon"的皇后区餐厅。curl http://localhost:8080/restaurants/browse按菜系类型检索餐厅。
以下命令会查询
cuisine值为"Czech"的餐厅,但您可以将此参数替换为任何菜系:curl http://localhost:8080/restaurants/cuisine/Czech
恭喜您完成 Quarkus 快速入门教程!完成这些步骤后,您就拥有一个Java Quarkus REST API ,它可以连接到MongoDB 部署、对示例餐厅数据运行查询,并通过HTTP终结点公开结果,您可以使用 curl 命令测试这些终结点。
其他资源
要学习有关 Quarkus、JNoSQL 和 MongoDB 的更多信息,请参阅以下资源:
Quarkus 文档