关于在Quarkus Reactive SQL Clients教程的Create端点通过Multipart请求提交多个Fruit对象的技术问询及示例需求
Great question! Yes, you absolutely can handle multiple JSON-formatted Fruit objects in a single multipart request with Quarkus and JAX-RS. Let’s break down the implementation on both the server and client side, tailored to align with the Reactive SQL Clients tutorial you followed.
Server-Side Implementation (Quarkus/JAX-RS)
First, you’ll need to add a new endpoint to your existing FruitResource that accepts multipart form data, where each part is a JSON-serialized Fruit object. Here’s how to do it:
- Update the Resource Class
Add a new POST endpoint that consumesmultipart/form-dataand accepts a list ofFruitobjects via form parameters. We’ll use Quarkus’s built-in support for automatic JSON-to-object conversion when parts are marked with the correct content type.
@Path("/fruits") @Produces(MediaType.APPLICATION_JSON) public class FruitResource { @Inject PgPool client; // Existing single-fruit create endpoint (keep this if needed) @POST @Consumes(MediaType.APPLICATION_JSON) public Uni<Void> create(Fruit fruit) { return client.query("INSERT INTO fruits (name) VALUES ($1)") .execute(Tuple.of(fruit.getName())) .map(res -> null); } // New bulk endpoint for multipart requests @POST @Path("/bulk") @Consumes(MediaType.MULTIPART_FORM_DATA) public Uni<Void> createMultiple(@FormParam("fruit") List<Fruit> fruits) { // Build a batch insert query for efficiency String batchSql = "INSERT INTO fruits (name) VALUES " + String.join(", ", Collections.nCopies(fruits.size(), "($1)")); // Map each Fruit to a Tuple for the batch List<Tuple> params = fruits.stream() .map(fruit -> Tuple.of(fruit.getName())) .collect(Collectors.toList()); // Execute the batch insert with the reactive client return client.query(batchSql) .executeBatch(params) .map(batchResult -> null); } }
Key Notes:
- The
@FormParam("fruit") List<Fruit>annotation tells JAX-RS to collect all multipart parts namedfruitinto a list. Each part must have aContent-Type: application/jsonheader for the conversion to work. - Using
executeBatch()instead of looping single inserts is far more efficient for reactive workloads, as it minimizes database round-trips.
Client-Side Example (jQuery Ajax)
To send the multipart request from JavaScript, you’ll need to build a FormData object where each entry is a JSON-serialized Fruit wrapped in a Blob (to set the correct content type). Here’s a working example:
// Sample list of Fruit objects to send const fruitsToAdd = [ { name: "Mango" }, { name: "Pineapple" }, { name: "Kiwi" } ]; // Initialize FormData const formData = new FormData(); // Add each Fruit as a separate multipart part fruitsToAdd.forEach(fruit => { // Convert the Fruit object to JSON string const fruitJson = JSON.stringify(fruit); // Create a Blob with the JSON and set content type to application/json const fruitBlob = new Blob([fruitJson], { type: "application/json" }); // Append to FormData with the name "fruit" (matches server's @FormParam) formData.append("fruit", fruitBlob); }); // Send the request with jQuery Ajax $.ajax({ url: "/fruits/bulk", method: "POST", data: formData, // Critical: Disable jQuery's automatic data processing and content-type setting processData: false, contentType: false, success: function() { console.log("All fruits added successfully!"); }, error: function(xhr, status, err) { console.error("Failed to add fruits:", err); } });
Key Notes:
- Setting
processData: falseandcontentType: falseis mandatory—this lets the browser handle the multipart boundary and content type headers automatically. - Each
Blobensures the server recognizes the part as JSON, triggering the correct message body reader to convert it to aFruitobject.
内容的提问来源于stack exchange,提问作者user2431672

