2013-09-05 12 views
5

Ich habe einen Controller mit einer Methode GET wie so geschrieben:Spring Web MVC, @ModelAttribute und @RequestParam zusammen

@Controller 
public class ThingController { 

    @RequestMapping(value = "/Thing.html", method = RequestMethod.GET) 
    public String editThing(@RequestParam("thingId") String thingId, @ModelAttribute ThingBean thing, BindingResult result) { 
     thing = <some service call using thingId> 
     logger.debug("The thing to edit is {}", thingBean); 
     return "thing/edit"; 
    } 
} 

Die Bohne ist richtig (Getter und Setter), der Service Aufruf gibt die richtige ThingBean mit Die ThingId, und meine JSP-Seite bei thing/edit.jsp zeigt sich.

Die JSP ist:

<html> 
<body> 
    <h1 id="title" class="title">Edit Thing</h1> 

<form:form id="thing" modelAttribute="thing"> 
    <form:input path="subject" id="subject" tabindex="1" /> 
    <form:textarea path="message" /> 

</form:form> 

</body> 
</html> 

Dennoch zeigt die JSP leere Werte für den Betreff und die Nachricht. Ja, es gibt Getter/Setter für diese Eigenschaften.

Ich habe einen sehr ähnlichen Controller, der gut funktioniert, nur gibt es kein @RequestParam in der Signatur der GET - mapped Methode dort.

Ich habe nirgendwo in der Frühjahr WebMVC Dokumentation gesehen, die besagt, dass ich das nicht tun kann - warum funktioniert es nicht? Warum wird das aktualisierte ModelAttribute-Objekt nicht in das JSP-Formular eingebunden?

EDIT:

Dieser Controller, und das gleiche Muster für GET Anrufe hat viele vielen verschiedenen Orten gearbeitet - die Variable mit @ModelAttribute kommentierte wird durch das Verfahren dann für die JSP-Seite angezeigt werden ausgefüllt. Warum hört es auf, indem eine @RequestParam-Annotation hinzugefügt wird?

@RequestMapping(value = "/Things.html", method = RequestMethod.GET) 
public String getThings(@ModelAttribute ThingForm thingForm, BindingResult result) { 

    try { 
     // need to get list of Things 
     List<Thing> Things = <service call that gets list of Things>; 
     thingForm.setThings(Things); 
     logger.debug("Things are {}", Things); 

    } 
    catch (ResourceNotFoundException e) { 
     return "error"; 
    } 

    logger.debug("Thing list loading - end"); 

    // Go to jsp 
    return "thing/list"; 
} 
+0

Können Sie uns Ihre anderen controller.and zeigen Was M.Deinum gesagt hat, richtig ist. – beinghuman

+0

Bearbeitete Frage zum Hinzufügen eines Gegenbeispiels. –

+1

Wie ich in meiner Antwort in dem Controller, den Sie gepostet haben, erwähnt habe, dass Sie ** eine Variable neu zuweisen (das Methodenargument), verändern Sie NICHT das Objekt, das Sie an die Methode übergeben. In der Steuerung sagst du, dass es funktioniert, dass du ** etwas zu einem Objekt hinzufügst, das als Modellobjekt fungiert. Grundsätzlich ist das ganz anders. –

Antwort

7

Das Problem ist, dass Sie nur einen neuen Verweis auf eine Sache zuweisen, die nie in Java funktioniert. Sie müssen es in das Modell einfügen, sonst wird es Ihnen nicht bekannt sein.

@RequestMapping(value = "/Thing.html", method = RequestMethod.GET) 
public String editThing(@RequestParam("thingId") String thingId, @ModelAttribute ThingBean thing, BindingResult result) { 
    thing = <some service call using thingId> // This is only assigning a new reference not updating 
    logger.debug("The thing to edit is {}", thingBean); 
    return "thing/edit"; 
} 

Anstatt also tun, um diese

@RequestMapping(value = "/Thing.html", method = RequestMethod.GET) 
public String editThing(@RequestParam("thingId") String thingId, @ModelAttribute ThingBean thing, BindingResult result, Model model) { 
    thing = <some service call using thingId> 
    model.addAttribute("thing", thing); 
    logger.debug("The thing to edit is {}", thingBean); 
    return "thing/edit"; 
} 

Was mich macht sich fragen, warum Sie sogar ein Modellattribut in diesem Verfahren haben? Es ist im Grunde nutzlos.

Anstelle der oben ich so etwas wie diese

@ModelAttribute("thing") 
public Thing prepareModel(@RequestParam("thingId") String thingId) { 
    return thingSergice.findById(thingId); 
} 

Nun ist diese Methode vor jedem Request Handling Methode wird aufgerufen tun würde. In dem Sie sich einfach darauf beziehen können, anstatt jedes Mal nachsehen zu müssen. (Und die Beurteilung aus dem Code Ihrer Thingbean Modell Attribut in Ihrer Methode ist ziemlich nutzlos ich, dass die folgenden neu schreiben würde)

@RequestMapping(value = "/Thing.html", method = RequestMethod.GET) 
public String editThing() { 
    return "thing/edit"; 
} 
+0

Also habe ich ein Gegenbeispiel hinzugefügt, und dieses Muster hat immer und immer wieder funktioniert. Die mit ModelAttribute annotierte Variable wurde von der Methode GET-annotiert aktualisiert und war in der JSP verfügbar. Der einzige Unterschied zu meinem neuen war, dass ich den annotierten Parameter RequestParam hinzugefügt habe. –

+0

Wie ich in meinem anderen Kommentar erwähnt habe, sind sie nicht die gleichen ... In dem, der nicht funktioniert, wirst du ** neu zuweisen, während der andere ** das Modellobjekt aktualisiert **. –

+0

ARGH. Dummes Programmierer-Syndrom. Ich habe in letzter Zeit zu viel Side-C-Programmierung gemacht. Danke, natürlich sehe ich es jetzt. –

1

Sie haben vergessen geben Sie den ModelAttribute Namen, die Verwendung folgende Korrektur:

public String editThing(@RequestParam("thingId") String thingId, 
@ModelAttribute("thing") ThingBean thing, BindingResult result) { 
.... 
} 

Wenn oben nicht Gebrauch funktioniert dies:

public String editThing(@RequestParam("thingId") String thingId, 
    @ModelAttribute("thing") ThingBean thing, BindingResult result, Model model) { 
      .... 
    thing = <some service call using thingId> 
    logger.debug("The thing to edit is {}", thingBean); 
    model.addAttribute("thing",thing); 
    return "thing/edit"; 
} 

Wenn möglich, empfehle ich besser Namensgebung Konvention für Komponenten, zum Beispiel- thingModel anstelle von thing. Dies fördert eine bessere Lesbarkeit für Sie und andere.

+0

Ich habe Produktionscode redigiert. Vertrauen Sie mir, es heißt besser als "Sache" –

+0

Übrigens, Sie müssen keinen Namen in Java 8 angeben. – naXa

Verwandte Themen