Model, ModelMap и ModelAndView

В Spring MVC модель — набор атрибутов, который контроллер передаёт представлению. Это данные одного web-запроса для рендеринга, а не доменная модель и не место для долгоживущего состояния.

Model

org.springframework.ui.Model — интерфейс. Spring передаёт его в метод контроллера:

@GetMapping("/greeting")
public String greeting(Model model) {
    model.addAttribute("message", "Hello");
    model.addAttribute("count", 10);
    return "greeting";
}

Строка greeting — логическое имя view. ViewResolver выбирает шаблон, а его движок читает message и count.

Основные операции:

model.addAttribute("key", value);
model.addAllAttributes(attributes);
model.containsAttribute("key");
model.asMap();

ModelMap

org.springframework.ui.ModelMap расширяет LinkedHashMap<String, Object> и добавляет удобные методы addAttribute. Его также можно принять параметром метода контроллера:

@GetMapping("/profile")
public String profile(ModelMap model) {
    model.addAttribute("mode", "compact");
    return "profile";
}

ModelMap не реализует интерфейс Model. Общая реализация ExtendedModelMap одновременно расширяет ModelMap и реализует Model.

ModelAndView

org.springframework.web.servlet.ModelAndView хранит и имя представления, и модель:

@GetMapping("/greeting")
public ModelAndView greeting() {
    ModelAndView result = new ModelAndView("greeting");
    result.addObject("message", "Hello");
    return result;
}

Он удобен, когда объект результата собирается как единое значение или передаётся через общий обработчик. Для обычного MVC-контроллера возврат имени view и параметр Model чаще читаются проще.

Важные границы

  • атрибуты модели существуют в рамках обработки запроса;
  • для redirect обычная модель может превратиться в query-параметры — специальные параметры задаёт RedirectAttributes;
  • flash attributes переживают один redirect через FlashMap;
  • секреты и крупные объекты нельзя бездумно класть в модель;
  • REST-контроллер с @ResponseBody сериализует возвращаемое значение и обычно не использует view model.

Самопроверка

  • Чем MVC-модель отличается от доменной модели?
  • Реализует ли ModelMap интерфейс Model?
  • Когда нужен ModelAndView, а когда достаточно строки и Model?