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集群,并设立应用程序结构。
创建 MongoDB Atlas 集群。
MongoDB Atlas是一项完全托管云数据库服务,用于托管MongoDB部署。如果您没有MongoDB 部署,可以通过完成MongoDB入门教程来免费创建MongoDB 集群。 MongoDB入门教程还演示了如何将示例数据集加载到集群中,包括本教程中使用的sample_restaurants 数据库。
要连接到MongoDB 集群,必须使用连接字符串。要学习;了解如何检索连接字符串,请参阅MongoDB入门教程的添加连接字符串部分。
重要
将连接string保存在安全位置。
配置数据库连接。
导航到 src/main/resources/application.properties文件并添加以下配置属性:
jnosql.document.database=sample_restaurants quarkus.mongodb.connection-string=<connection string>
此代码将配置与MongoDB 集群中 sample_restaurants数据库的连接。将 <connection string> 占位符替换为在上一步中保存的连接字符串。
清理模板文件。
Quarkus项目模板包含一些示例文件,您可以在本教程中删除这些文件。要删除这些不需要的文件,请选择与操作系统对应的标签页,然后从 quarkus-quickstart目录运行以下命令:
rm src/main/java/org/acme/Car.java rm src/main/java/org/acme/Garage.java rm src/test/java/org/acme/GarageTest.java rm src/main/java/org/acme/GreetingResource.java rm src/test/java/org/acme/GreetingResourceIT.java rm src/test/java/org/acme/GreetingResourceTest.java
del src/main/java/org/acme/Car.java del src/main/java/org/acme/Garage.java del src/test/java/org/acme/GarageTest.java del src/main/java/org/acme/GreetingResource.java del src/test/java/org/acme/GreetingResourceIT.java del src/test/java/org/acme/GreetingResourceTest.java
创建应用程序
设置项目结构和依赖项后,请按照本节中的步骤创建数据模型、存储库类和 REST 终结点。
创建 Restaurant 模型。
在 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. */ public class Restaurant { private String id; private String name; private String borough; 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 的文件,然后粘贴以下代码:
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. * */ public 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 的文件并粘贴以下代码:
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. */ public class RestaurantResource { RestaurantRepository restaurantRepository; /** * Retrieves all restaurants from the database. * * @return List of all restaurants */ 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 */ 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 */ public Response getRestaurantsByCuisine( 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 的文件并粘贴以下代码:
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. */ public class RestaurantRepositoryTest { RestaurantRepository restaurantRepository; public void testRetrieveRestaurants() { // Test repository injection and MongoDB connection assertThat(restaurantRepository).isNotNull(); } 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/ [{"id":"...","name":"Morris Park Bake Shop","borough":"Bronx","cuisine":"Bakery"}, {"id":"...","name":"Wilken'S Fine Food","borough":"Brooklyn","cuisine":"Delicatessen"}, {"id":"...","name":"Taste The Tropics Ice Cream","borough":"Brooklyn","cuisine":"Ice Cream, Gelato, Yogurt, Ices"}, {"id":"...","name":"Carvel Ice Cream","borough":"Queens","cuisine":"Ice Cream, Gelato, Yogurt, Ices"}, ...] 检索名称中包含
"Moon"的皇后区餐厅。curl http://localhost:8080/restaurants/browse [{"id":"...","name":"Somoon","borough":"Queens","cuisine":"Asian"}, {"id":"...","name":"New Moon Star Restaurant","borough":"Queens","cuisine":"Chinese"}, {"id":"...","name":"Moon Tikka Grill","borough":"Queens","cuisine":"Indian"}, {"id":"...","name":"Silver Moon Diner","borough":"Queens","cuisine":"American"}, {"id":"...","name":"Mooney'S Public House","borough":"Queens","cuisine":"Irish"}, {"id":"...","name":"Moon Light Crill Rest.","borough":"Queens","cuisine":"Indian"}, {"id":"...","name":"Full Moon Cafe","borough":"Queens","cuisine":"Café/Coffee/Tea"}, {"id":"...","name":"Pacific Moon","borough":"Queens","cuisine":"Chinese"}, {"id":"...","name":"Moon Palace Kitchen","borough":"Queens","cuisine":"Chinese"}, {"id":"...","name":"Honey Moon Coffee Shop 1766096115682","borough":"Queens","cuisine":"Café/Coffee/Tea"}, {"id":"...","name":"Honey Moon Coffee Shop","borough":"Queens","cuisine":"Café/Coffee/Tea"}] 按菜系类型检索餐厅。
以下命令会查询
cuisine值为"Czech"的餐厅,但您可以将此参数替换为任何菜系:curl http://localhost:8080/restaurants/cuisine/Czech [{"id":"...","name":"Koliba Restaurant","borough":"Queens","cuisine":"Czech"}, {"id":"...","name":"Milan'S Restaurant","borough":"Brooklyn","cuisine":"Czech"}, {"id":"...","name":"Bohemian Beer Garden","borough":"Queens","cuisine":"Czech"}, {"id":"...","name":"Hospoda","borough":"Manhattan","cuisine":"Czech"}, {"id":"...","name":"Olde Prague Tavern","borough":"Queens","cuisine":"Czech"}, {"id":"...","name":"Brooklyn Beet Company","borough":"Brooklyn","cuisine":"Czech"}]
恭喜您完成 Quarkus 快速入门教程!完成这些步骤后,您就拥有一个Java Quarkus REST API ,它可以连接到MongoDB 部署、对示例餐厅数据运行查询,并通过HTTP终结点公开结果,您可以使用 curl 命令测试这些终结点。
其他资源
要学习有关 Quarkus、JNoSQL 和 MongoDB 的更多信息,请参阅以下资源:
Quarkus 文档