Die Annotation @ModelAttribute
in diesem Fall wird verwendet, um ein Objekt zu identifizieren, das Spring als Modellattribut hinzufügen sollte. Modellattribute sind eine Abstraktion von den Attributen HttpServletRequest
. Im Grunde genommen handelt es sich um Objekte, die durch einen Schlüssel identifiziert werden, der seinen Weg in die HttpServletRequest
Attribute findet. Sie können dies tun, indem Sie manuell ein Attribut mit Model#addAttribute(String, Object)
hinzufügen, eine annotierte Methode @ModelAttribute
haben oder einen Methodenparameter mit @ModelAttribute
annotieren.
Die Sache, die Sie verstehen müssen, ist, wie Spring Ihre Handler-Methode Parameter löst und Argumente eingibt. Dazu wird die Schnittstelle HandlerMethodArgumentResolver
verwendet. Es gibt eine Reihe von Implementierungsklassen (siehe Javadoc), und jeder trägt die Verantwortung für resolveArgument()
, indem er das Argument, das Spring verwendet, an invoke()
Ihre Handler-Methode durch Reflektion zurückgibt.Spring ruft nur die Methode resolveArgument()
auf, wenn die Methode HandlerMethodArgumentResolver
supportsParameter()
den spezifischen Parameter true
zurückgibt.
Die HandlerMethodArgumentResolver
Umsetzung in Frage hier ist ServletModelAttributeMethodProcessor
die von ModelAttributeMethodProcessor
erstreckt, die mit @ModelAttribute kommentierten
Resolves Methodenargumente erklärt und behandelt Rückgabewerte von Methoden mit @ModelAttribute kommentiert.
Spring (3.2) wird register diese HandlerMethodArgumentResolver
und andere
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;
}
Wenn der Frühling braucht Ihre Handler-Methode aufzurufen, ist es durch die Parametertypen und durch die oben aufgeführte Liste laufen werden und verwenden Sie die erste dass supportsParameter()
.
Beachten Sie, dass zwei Instanzen von ServletModelAttributeMethodProcessor
hinzugefügt werden (einer nach einem //catch all
Kommentar). Die ModelAttributeMethodProcessor
hat ein annotationNotRequired
Feld, das sagt, ob es nach der @ModelAttribute
oder nicht suchen sollte. Die erste Instanz muss nach @ModelAttribute
suchen, die zweite nicht. Spring tut dies, so dass Sie Ihre eigenen HandlerMethodArgumentResolver
Instanzen registrieren können, siehe // Custom arguments
Kommentar.
Speziell
@RequestMapping(value = "/", method = RequestMethod.POST)
public String sayHello(Person person, Model model) {
model.addAttribute("person", person);
return "home";
}
In diesem Fall spielt es keine Rolle, ob Ihre Person
Parameter oder nicht kommentiert wird. A ModelAttributeMethodProcessor
löst es auf und bindet Formularfelder, dh. Anforderungsparameter an die Felder der Instanz. Sie sollten es nicht einmal zur model
hinzufügen müssen, da die ModelAttributeMethodProcessor
Klasse das handhaben wird.
In Ihrer showHelloPage()
Methode
model.addAttribute("person", new Person());
mit dem <form>
taglib benötigt. So löst es seine input
Felder auf.
Also meine Frage ist - was ist die Verwendung des "ModelAttribute" anonnatation?
Zum automatischen Hinzufügen des angegebenen Parameters (oder Methodenrückgabewerts) zum Modell.
Ist es eine Möglichkeit, ein "ModelAttribute" -Attribut in einem Formular wegzulassen?
Nein, die form
Bindung sieht für ein Objekt in der Model
und bindet seine Felder input
Elemente in HTML.
Und der zweite Teil, was ist die Art und Weise (vielleicht einige Anmerkung) eine Form automatisch binden Eingänge Werte der richtigen Bohne Eigenschaften (die als Methodenparameter deklariert werden würde) zu machen? Ohne eine leere Bean vor dem Senden eines Formulars hinzufügen (wie ich es jetzt tun muss).
A Feder <form>
tag klinkt ein Modellobjekt-Attribut und verwendet seine Felder input
und label
Elemente zu schaffen. Es spielt keine Rolle, wie das Objekt so lange im Modell landete. Wenn es kein Modellattribut mit dem von Ihnen angegebenen Namen (Schlüssel) findet, werden Ausnahmen ausgelöst, wie Sie gesehen haben.
<form:form method="post" modelAttribute="person">
Die Alternative zur Bereitstellung einer leeren Bean besteht darin, den HTML-Code selbst zu erstellen. Alle <form>
von Spring verwendet die Feldnamen der Bean, um ein input
-Element zu erstellen. Also das
<form:form method="post" modelAttribute="person">
<form:label path="firstName">First name</form:label>
<form:input path="firstName" />
schafft so etwas wie
<form method="post" action="[some action url]">
<label for="firstName">First name<label>
<input type="text" name="firstName" value="[whatever value firstName field had]" />
...
Frühling bindet Anforderungsparameter auf Instanzfelder mit dem Attribut name
.
Vielen Dank für Ihre Antwort, Sie haben mir eine Menge erklärt. Nur noch eine Frage zu der Annotation "ModelAttribute" - wenn ich Sie richtig verstehe, ist diese Annotation, die mit einem Methodenparameter verwendet wird, äquivalent zu "model.addAttribute (...)"? –
@ MichałTabor Versuchen Sie, es als Methodenparameter hinzuzufügen. Ich bin mir nicht sicher, ob, weil die Anfrage keine Anfrageparameter hat, die gebunden werden können, sie 'null' zurückgibt. Ansonsten ist die Art, wie Sie vorgehen, der richtige Weg. Diese werden als Datenübertragungsobjekte (oder Spring form backing objects/command objects) bezeichnet. Die Dokumentation sollte mehr Details enthalten. –
+1, große Erklärung – rocketboy