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

Spring MVC и аннотация @ModelAttribute

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

1. Обзор

Одной из наиболее важных аннотаций Spring MVC является аннотация @ModelAttribute .

@ModelAttribute — это аннотация, которая связывает параметр метода или возвращаемое значение метода с именованным атрибутом модели, а затем предоставляет его веб-представлению.

В этом уроке мы продемонстрируем удобство использования и функциональность этой аннотации с помощью общей концепции — формы, представленной сотрудником компании.

2. @ModelAttribute в деталях

Как было показано во вступительном абзаце, мы можем использовать @ModelAttribute либо в качестве параметра метода, либо на уровне метода.

2.1. На уровне метода

Когда мы используем аннотацию на уровне метода, это указывает на то, что целью метода является добавление одного или нескольких атрибутов модели. Такие методы поддерживают те же типы аргументов, что и методы @RequestMapping , но их нельзя напрямую сопоставлять с запросами.

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

@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("msg", "Welcome to the Netherlands!");
}

В приведенном выше примере мы видим метод, который добавляет атрибут с именем msg ко всем моделям, определенным в классе контроллера.

Конечно, мы увидим это в действии позже в статье.

Как правило, Spring MVC всегда сначала вызывает этот метод, прежде чем вызывать какие-либо методы обработчика запросов. По сути, методы @ModelAttribute вызываются до вызова методов контроллера, аннотированных с помощью @RequestMapping . Это связано с тем, что объект модели должен быть создан до начала какой-либо обработки внутри методов контроллера.

Также важно, чтобы мы аннотировали соответствующий класс как @ControllerAdvice . Таким образом, мы можем добавить в модель значения , которые будут идентифицированы как глобальные. На самом деле это означает, что для каждого запроса существует значение по умолчанию для каждого метода в ответе.

2.2. Как аргумент метода

Когда мы используем аннотацию в качестве аргумента метода, она указывает на получение аргумента из модели. Если аннотация отсутствует, ее следует сначала создать, а затем добавить в модель. После присутствия в модели поля аргументов должны заполняться всеми параметрами запроса, имеющими совпадающие имена.

В следующем фрагменте кода мы заполним атрибут модели сотрудника данными из формы, отправленной в конечную точку addEmployee . Spring MVC делает это за кулисами перед вызовом метода отправки:

@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(@ModelAttribute("employee") Employee employee) {
// Code that uses the employee object

return "employeeView";
}

Позже в этой статье мы увидим полный пример того, как использовать объект employee для заполнения шаблона employeeView .

Он связывает данные формы с bean-компонентом. Контроллер, аннотированный с помощью @RequestMapping , может иметь настраиваемые аргументы класса, аннотированные с помощью @ModelAttribute .

В Spring MVC мы называем это привязкой данных, общим механизмом, который избавляет нас от необходимости анализировать каждое поле формы по отдельности.

3. Пример формы

В этом разделе мы рассмотрим пример, описанный в разделе «Обзор», очень простую форму, которая предлагает пользователю (в частности, сотруднику компании) ввести некоторую личную информацию (в частности, имя и идентификатор). После завершения отправки и без каких-либо ошибок пользователь ожидает увидеть ранее отправленные данные, отображаемые на другом экране.

3.1. Вид

Давайте сначала создадим простую форму с полями id и name:

<form:form method="POST" action="/spring-mvc-basics/addEmployee" 
modelAttribute="employee">
<form:label path="name">Name</form:label>
<form:input path="name" />

<form:label path="id">Id</form:label>
<form:input path="id" />

<input type="submit" value="Submit" />
</form:form>

3.2. Контроллер

Вот класс контроллера, в котором мы реализуем логику вышеупомянутого представления:

@Controller
@ControllerAdvice
public class EmployeeController {

private Map<Long, Employee> employeeMap = new HashMap<>();

@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(
@ModelAttribute("employee") Employee employee,
BindingResult result, ModelMap model) {
if (result.hasErrors()) {
return "error";
}
model.addAttribute("name", employee.getName());
model.addAttribute("id", employee.getId());

employeeMap.put(employee.getId(), employee);

return "employeeView";
}

@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("msg", "Welcome to the Netherlands!");
}
}

В методе submit() у нас есть объект Employee , привязанный к нашему представлению . Мы можем просто сопоставить наши поля формы с объектной моделью. В методе мы извлекаем значения из формы и устанавливаем их в ModelMap .

В конце концов, мы возвращаем employeeView , что означает, что мы вызываем соответствующий JSP-файл в качестве представителя представления.

Кроме того, есть еще метод addAttributes() . Его цель — добавить значения в модель , которые будут идентифицированы глобально. То есть каждый запрос к каждому методу контроллера будет возвращать значение по умолчанию в качестве ответа. Мы также должны аннотировать конкретный класс как @ControllerAdvice.

3.3. Модель

Как упоминалось ранее, объект « Модель » очень прост и содержит все, что требуется для «внешних» атрибутов. Теперь давайте посмотрим на пример:

@XmlRootElement
public class Employee {

private long id;
private String name;

public Employee(long id, String name) {
this.id = id;
this.name = name;
}

// standard getters and setters removed
}

3.4. Заворачивать

@ControllerAdvice помогает контроллеру и, в частности, методам @ModelAttribute , которые применяются ко всем методам @RequestMapping . Конечно, наш метод addAttributes() будет запускаться первым, до остальных методов @RequestMapping .

Имея это в виду, после запуска обоих методов submit() и addAttributes() мы можем ссылаться на них в представлении , возвращаемом из класса Controller , упомянув их имя внутри пары долларовых фигурных скобок, например ${name} .

3.5. Просмотр результатов

Теперь выведем то, что мы получили из формы:

<h3>${msg}</h3>
Name : ${name}
ID : ${id}

4. Вывод

В этой статье мы исследовали использование аннотации @ModelAttribute как для аргументов метода, так и для вариантов использования на уровне метода .

Реализацию этой статьи можно найти в проекте github .