Spring: привязка объекта с и без @ModelAttribute
Я новичок в Spring и регистрирую пользователя. Мне это понравилось.
@RequestMapping("/register")
public String register(@ModelAttribute User user,BindingResult result){
if(!result.hasErrors()){
userSerive.register(user);
}
return "welcome";
}
Это сработало отлично, но проблема здесь в том, что мне не нужен этот объект user
на моей странице welcome.jsp
, поэтому зачем делать объект модели более тяжелым. Поэтому я пробовал без @ModelAttribute
, это также работает для меня, как показано ниже.
@RequestMapping("/register")
public String register(User user,BindingResult result){
if(!result.hasErrors()){
userSerive.register(user);
}
return "welcome";
}
Итак, я просто хочу знать, что за плюсы и минусы обоих и , что является лучшей практикой, если мне действительно не нужен объект user
в jsp
. Является ли @ModelAttribute
любая другая вещь, кроме добавления объекта к модели, которая Spring неявная привязка не делает. Is @ModelAttribute
более безопасный способ привязки или иначе?
Я хочу классифицировать свой запрос в следующем 4-х типах запроса. Какая разница с и без @ModelAttribute
, если мне не нужно отправлять данные в поле зрения, а мой запрос - любой из <
- строка запроса, т.е. данные формы в GET
- запрашивать полезную нагрузку или тело, т.е. данные формы в POST
- данные json в ajaxified GET requst
- данные json в POST requst - я думаю, это не было бы связью ни в одном из них.
@RequestBody
.
Ответы
Ответ 1
Вероятно (см. ниже...) нет различия в поведении между двумя сигнатурами метода в вашем случае.
Оба свяжут параметры запроса с user
и добавят результирующий объект к модели как атрибут user
- это имя атрибута происходит от декапитализированного имени типа аргумента метода user
.
@ModelAttribute
можно использовать для настройки имени атрибута, например. @ModelAttribute("theUser")
, или дать подсказку читателю вашего кода, что этот аргумент используется в представлении. Но, как вы говорите, ни один из них не применяется в вашем случае использования.
Точно такой же код в Spring будет использоваться для заполнения аргумента независимо от того, используете ли вы аннотацию @ModelAttribute
или нет - данный код org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor
.
Поэтому для меня больше смысла использовать подпись public String register(User user, BindingResult result)
в вашем коде. Добавление аннотации @ModelAttribute
к аргументам метода, которые не требуются в модели, может смущать людей, читающих ваш код.
Несколько более длинный ответ заключается в том, что в вашем случае может быть причина для указания @ModelAttribute
, но это довольно загадочно и маловероятно.
аргументы метода в методах обработчика Spring заполняются экземплярами HandlerMethodArgumentResolver
. Они настраиваются и, в свою очередь, предпринимаются попытки для каждого параметра.
Решатели аргументов метода обработчика по умолчанию выглядят следующим образом (см. RequestMappingHandlerAdapter
):
resolvers.add(new ServletModelAttributeMethodProcessor(false));
...
resolvers.add(new ServletModelAttributeMethodProcessor(true));
Если вы должны добавить свой собственный в середине, например. a UserHandlerMethodArgumentResolver
, вы можете использовать @ModelAttribute
, чтобы сообщить Spring обрабатывать определенный аргумент по умолчанию, а не использовать свой собственный класс распознавания аргументов.
Ответ 2
Помимо добавления объекта в Model, Spring MVC использует его для предоставления связанного объекта методу Controller, где вы можете его использовать, в вашем случае для "регистрации".
И да @ModelAtttribute является самым безопасным и лучшим способом в Spring MVC для привязки входящих сообщений к объекту.
Ответ 3
Этот вопрос очень полезен, но я не вижу ответа здесь правильно ответить на вопрос.
Я прочитал больше потоков в stackoverflow и нашел, что это очень полезно:
fooobar.com/questions/24439/...
Для себя как решить, какой из них использовать, если мне нужна привязка и я не хочу хранить объект параметра в модели, тогда не используйте @ModelAttribute
.
Ответ 4
Как описано в документации Spring MVC - аннотация @ModelAttribute может использоваться для методов или аргументов метода. И, конечно же, мы можем одновременно использовать оба контроллера.
аннотация метода
@ModelAttribute("person")
public Person getPerson(){
return new Person();
}
Цель такого метода - добавить атрибут в модель. Таким образом, в нашем случае ключ человека будет иметь объект-объект как значение в Модели. Методы @ModelAttribute в контроллере вызываются перед методами @RequestMapping внутри одного контроллера.
Аргумент метода
public String processForm(@ModelAttribute("person") Person person){
person.getStuff();
}
См. документацию Spring http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib-method-args
Ответ 5
Отметьте этот пост здесь. Он содержит подробные сведения о ModelAttribute.
ModelAttribute может использоваться только с запрошенными формами данными запроса. Он не может связывать данные запроса json/xml с объектами данных. Для этого вам нужно будет использовать RequestBody.
Ответ 6
в дополнение к отличному ответу @ryanp, я бы хотел добавить:
для современного проекта spring mvc, наиболее вероятно, что он будет использовать аннотации, такие как @Controller и @RequestMapping и т.д., чтобы предоставить обработчик запроса, внутри, spring MVC использует RequestMappingHandlerAdapter.invokeHandlerMethod() для обработки запроса с пользователем предоставленный HandlerMethod. если вы посмотрите на RequestMappingHandlerAdapter, он настроит коллекцию аргумента resolver для подготовки аргумента для HandlerMethod, посмотрев на набор, вы поймете, как и в каком порядке spring запрос анализа синтаксиса MVC и заполняет предоставленные пользователем аргументы. поэтому здесь исходный код:
`` `Java
/**
* Return the list of argument resolvers to use including built-in resolvers
* and custom resolvers provided via {@link #setCustomArgumentResolvers}.
*/
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 PathVariableMapMethodArgumentResolver());
resolvers.add(new MatrixVariableMethodArgumentResolver());
resolvers.add(new MatrixVariableMapMethodArgumentResolver());
resolvers.add(new ServletModelAttributeMethodProcessor(false));
resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory()));
resolvers.add(new RequestHeaderMapMethodArgumentResolver());
resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory()));
resolvers.add(new SessionAttributeMethodArgumentResolver());
resolvers.add(new RequestAttributeMethodArgumentResolver());
// Type-based argument resolution
resolvers.add(new ServletRequestMethodArgumentResolver());
resolvers.add(new ServletResponseMethodArgumentResolver());
resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
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;
}
`` `
Стоит отметить, что все ресиверы Catch-all внизу. spring MVC использует те же самые два резольвера, которые обрабатывают @RequestParam и @ModelAttribute для обработки не аннотированных простых типов и аргументов типа pojo соответственно. Вот почему в тесте OP не имеет значения, есть ли @ModelAttribute или нет.
Позор, который он не сделал кристально чистым в ссылке spring MVC.