Аннотации @ModelAttribute
в этом случае используются для идентификации объекта, который Spring должен добавить в качестве атрибута модели. Атрибуты модели - это абстракция от атрибутов HttpServletRequest
. В основном, это объекты, определенные некоторым ключом, которые найдут свой путь в атрибутах HttpServletRequest
. Вы можете сделать это, вручную добавив атрибут с Model#addAttribute(String, Object)
, используйте аннотированный метод @ModelAttribute
или аннотируя параметр метода с помощью @ModelAttribute
.
Что нужно понять, так это то, как Spring разрешает параметры метода обработчика и вводит аргументы. Для этого используется интерфейс HandlerMethodArgumentResolver
. Существует несколько классов реализации (см. Javadoc), и каждый из них несет ответственность за resolveArgument()
, возвращая аргумент, который Spring будет использовать для метода вашего обработчика с помощью рефлексии invoke()
.Spring вызовет только метод resolveArgument()
, если метод HandlerMethodArgumentResolver
supportsParameter()
возвращает true
для конкретного параметра.
HandlerMethodArgumentResolver
реализация в вопросе здесь является ServletModelAttributeMethodProcessor
, который простирается от ModelAttributeMethodProcessor
, которая гласит
аргументов методы Разрешает аннотированные с @ModelAttribute и обрабатывает возвращаемых значения из методов, аннотированных @ModelAttribute.
Spring (3,2) будет register это HandlerMethodArgumentResolver
и другие
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() {
List<HandlerMethodArgumentResolver> resolvers = new ArrayList<HandlerMethodArgumentResolver>();
// Annotation-based argument resolution
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false));
resolvers.add(new RequestParamMapMethodArgumentResolver());
resolvers.add(new PathVariableMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters()));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters()));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters()));
resolvers.add(new RedirectAttributesMethodArgumentResolver());
resolvers.add(new ModelMethodProcessor());
resolvers.add(new MapMethodProcessor());
resolvers.add(new ErrorsMethodArgumentResolver());
resolvers.add(new SessionStatusMethodArgumentResolver());
resolvers.add(new UriComponentsBuilderMethodArgumentResolver());
// Custom arguments
if (getCustomArgumentResolvers() != null) {
resolvers.addAll(getCustomArgumentResolvers());
}
// Catch-all
resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true));
resolvers.add(new ServletModelAttributeMethodProcessor(true));
return resolvers;
}
Когда весна должна вызывать ваш метод обработки, он будет перебирать типов параметров и через приведенный выше список и использовать первый это supportsParameter()
.
Обратите внимание, что добавляются два экземпляра ServletModelAttributeMethodProcessor
(один за комментарием //catch all
). ModelAttributeMethodProcessor
имеет поле annotationNotRequired
, в котором говорится, что он должен искать @ModelAttribute
или нет. Первый экземпляр должен искать @ModelAttribute
, второй - нет. Spring делает это так, что вы можете зарегистрировать свои собственные экземпляры HandlerMethodArgumentResolver
, см. Комментарий // Custom arguments
.
В частности
@RequestMapping(value = "/", method = RequestMethod.POST)
public String sayHello(Person person, Model model) {
model.addAttribute("person", person);
return "home";
}
В данном случае это не имеет значения, если параметр Person
помечается или нет. A ModelAttributeMethodProcessor
разрешит его и свяжет поля формы, т.е. параметры запроса, в поля экземпляра. Вам даже не нужно добавлять его в model
, так как класс ModelAttributeMethodProcessor
будет обрабатывать это.
В вашем showHelloPage()
методе
model.addAttribute("person", new Person());
необходимо с <form>
TagLib. Вот как он разрешает свои поля input
.
Так что мой вопрос - что такое использование "ModelAttribute" anonnatation?
Чтобы автоматически добавить указанный параметр (или возвращаемое значение метода) в модель.
Можно ли опустить атрибут «modelAttribute» в форме?
Нет, form
вяжущие выглядит для объекта в Model
и связывает свои поля HTML input
элементов.
И вторая часть, что путь (возможно, некоторые аннотаций), чтобы сделать формы автоматически связывать значения INPUTs' свойствам надлежащего бин (который был бы объявлен как параметр методы)? Без необходимости добавлять пустой bean-компонент перед отправкой формы (как я должен сделать это сейчас).
Весеннее <form>
тег впивается модель атрибутов объекта и использует свои поля для создания input
и label
элементов. Неважно, как объект оказался в модели до тех пор, пока он это сделал. Если он не может найти атрибут модели с указанным вами именем (ключом), он выдает исключения, как вы видели.
<form:form method="post" modelAttribute="person">
Альтернативой предоставлению пустого компонента является создание html самостоятельно. Все Spring <form>
does использует имена полей bean для создания элемента input
. Так что
<form:form method="post" modelAttribute="person">
<form:label path="firstName">First name</form:label>
<form:input path="firstName" />
Создает что-то вроде
<form method="post" action="[some action url]">
<label for="firstName">First name<label>
<input type="text" name="firstName" value="[whatever value firstName field had]" />
...
Spring связывает параметры запроса с полей экземпляра с помощью атрибута name
.
Большое спасибо за ваш ответ, вы мне многое объяснили. Еще один вопрос об аннотации «ModelAttribute» - если я правильно вас понимаю, эта аннотация, используемая с параметром метода, эквивалентна «model.addAttribute (...)»? –
@ MichałTabor Попробуйте добавить его как параметр метода. Я не уверен, если, поскольку запрос не имеет параметров запроса, которые могут быть связаны, он вернет 'null'. В противном случае, как вы это делаете, это правильный путь. Они называются объектами передачи данных (или объектами резервного копирования Spring или объектами команд). Документация должна содержать более подробную информацию. –
+1, отличное объяснение – rocketboy