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?