Перейти к основному содержимому

Обработка составных запросов в Spring

· 3 мин. чтения

1. Введение

В этом руководстве мы сосредоточимся на различных механизмах отправки составных запросов в Spring Boot. Составные запросы состоят из отправки данных множества разных типов, разделенных границей, как часть одного вызова метода HTTP.

Как правило, в этом запросе мы можем отправлять сложные данные JSON, XML или CSV, а также передавать составные файлы. Примеры файлов, состоящих из нескольких частей, включают аудиофайлы или файлы изображений. Кроме того, мы можем отправить данные простой пары ключ/значение с составным файлом (файлами) в виде составного запроса.

Теперь давайте рассмотрим различные способы отправки этих данных.

2. Использование @ModelAttribute

Давайте рассмотрим простой вариант использования отправки данных сотрудника, состоящих из имени и файла, с помощью формы.

Во- первых, мы создадим абстракцию Employee для хранения данных формы:

public class Employee {
private String name;
private MultipartFile document;
}

Затем мы создадим форму, используя Thymeleaf :

<form action="#" th:action="@{/employee}" th:object="${employee}" method="post" enctype="multipart/form-data">
<p>name: <input type="text" th:field="*{name}" /></p>
<p>document:<input type="file" th:field="*{document}" multiple="multiple"/>
<input type="submit" value="upload" />
<input type="reset" value="Reset" /></p>
</form>

Важно отметить, что мы объявляем enctype как multipart/form-data в представлении.

Наконец, мы создадим метод, который принимает данные формы, включая составной файл:

@RequestMapping(path = "/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public String saveEmployee(@ModelAttribute Employee employee) {
employeeService.save(employee);
return "employee/success";
}

Здесь две особенно важные детали:

  • значение атрибута потребляет значение multipart/form-data
  • @ModelAttribute зафиксировал все данные формы в POJO Employee , включая загруженный файл.

3. Использование @RequestPart

Эта аннотация связывает часть составного запроса с аргументом метода, что полезно для отправки сложных данных с несколькими атрибутами в качестве полезной нагрузки, например, JSON или XML.

Давайте создадим метод с двумя аргументами, первый типа Employee и второй MultipartFile . Кроме того, мы аннотируем оба этих аргумента с помощью @RequestPart :

@RequestMapping(path = "/requestpart/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public ResponseEntity<Object> saveEmployee(@RequestPart Employee employee, @RequestPart MultipartFile document) {
employee.setDocument(document);
employeeService.save(employee);
return ResponseEntity.ok().build();
}

Теперь, чтобы увидеть эту аннотацию в действии, мы создадим тест, используя MockMultipartFile :

@Test
public void givenEmployeeJsonAndMultipartFile_whenPostWithRequestPart_thenReturnsOK() throws Exception {
MockMultipartFile employeeJson = new MockMultipartFile("employee", null,
"application/json", "{\"name\": \"Emp Name\"}".getBytes());

mockMvc.perform(multipart("/requestpart/employee")
.file(A_FILE)
.file(employeeJson))
.andExpect(status().isOk());
}

Важно отметить выше, что мы установили тип содержимого части Employee как application/JSON . Мы также отправляем эти данные в виде файла JSON в дополнение к составному файлу.

Более подробную информацию о том, как тестировать составные запросы, можно найти здесь .

4. Использование @RequestParam

Другой способ отправки составных данных — использовать @RequestParam . Это особенно полезно для простых данных, которые отправляются в виде пар ключ/значение вместе с файлом :

@RequestMapping(path = "/requestparam/employee", method = POST, consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public ResponseEntity<Object> saveEmployee(@RequestParam String name, @RequestPart MultipartFile document) {
Employee employee = new Employee(name, document);
employeeService.save(employee);
return ResponseEntity.ok().build();
}

Давайте напишем тест для этого метода, чтобы продемонстрировать:

@Test
public void givenRequestPartAndRequestParam_whenPost_thenReturns200OK() throws Exception {
mockMvc.perform(multipart("/requestparam/employee")
.file(A_FILE)
.param("name", "testname"))
.andExpect(status().isOk());
}

5. Вывод

В этой статье мы узнали, как эффективно обрабатывать составные запросы в Spring Boot.

Изначально мы отправляли составные данные формы, используя атрибут модели. Затем мы рассмотрели, как отдельно получать составные данные с помощью аннотаций @RequestPart и @RequestParam .

Как всегда, полный исходный код доступен на GitHub .