web-dev-qa-db-fra.com

Annotation @ModelAttribute, quand l'utiliser?

Disons que nous avons une entité Person, un contrôleur PersonController et une page edit.jsp (création ou modification d'une personne existante)

Manette

@RequestMapping(value = "/edit", method = RequestMethod.POST)
public String editPerson(@RequestParam("fname") String fname, Model model) {
    if(fname == null || fname.length() == 0){
        model.addAttribute("personToEditOrCreate", new Person());
    }
    else{
        Person p = personService.getPersonByFirstName(fname);
        model.addAttribute("personToEditOrCreate", p);
    }

    return "persons/edit";
}

@RequestMapping(value = "/save", method = RequestMethod.POST)
public String savePerson(Person person, BindingResult result) {

    personService.savePerson(person);
    return "redirect:/home";
}

edit.jsp

<form:form method="post" modelAttribute="personToEditOrCreate" action="save">
    <form:hidden path="id"/> 
    <table>
        <tr>
            <td><form:label path="firstName">First Name</form:label></td>
            <td><form:input path="firstName" /></td>
        </tr>
        <tr>
            <td><form:label path="lastName">Last Name</form:label></td>
            <td><form:input path="lastName" /></td>
        </tr>
        <tr>
            <td><form:label path="money">Money</form:label></td>
            <td><form:input path="money" /></td>
        </tr>
        <tr>
            <td colspan="2">
                <input type="submit" value="Add/Edit Person"/>
            </td>
        </tr>
    </table> 

</form:form>

J'essaie le code ci-dessus (sans utiliser l'annotation @ModelAttribute dans la méthode savePerson et tout fonctionne correctement. Pourquoi et quand dois-je ajouter l'annotation à l'objet person:

@RequestMapping(value = "/save", method = RequestMethod.POST)
public String savePerson(@ModelAttribute("personToEditOrCreate") Person person, BindingResult result) {

    personService.savePerson(person);
    return "redirect:/home";
}
32
geo

Vous n'avez pas besoin de @ModelAttribute (paramètre) pour utiliser un bean comme paramètre

Par exemple, ces méthodes de gestionnaire fonctionnent correctement avec ces demandes:

@RequestMapping("/a")
void pathA(SomeBean someBean) {
  assertEquals("neil", someBean.getName());
}

GET /a?name=neil

@RequestMapping(value="/a", method=RequestMethod.POST)
void pathAPost(SomeBean someBean) {
  assertEquals("neil", someBean.getName());
}

POST /a
name=neil

Utilisez @ModelAttribute (méthode) pour charger données par défaut dans votre modèle à chaque demande, par exemple depuis une base de données, en particulier lorsque vous utilisez @SessionAttributes. Cela peut être fait dans une Controller ou dans une ControllerAdvice:

@Controller
@RequestMapping("/foos")
public class FooController {

  @ModelAttribute("foo")
  String getFoo() {
    return "bar";  // set modelMap["foo"] = "bar" on every request
  }

}

Toute JSP transmise à FooController:

${foo} //=bar

ou

@ControllerAdvice
public class MyGlobalData {

  @ModelAttribute("foo")
  String getFoo() {
    return "bar";  // set modelMap["foo"] = "bar" on every request
  }

}

Toute JSP:

${foo} //=bar

Utilisez @ModelAttribute (paramètre) si vous souhaitez utiliser le résultat de @ModelAttribute (méthode) en tant que default:

@ModelAttribute("attrib1")
SomeBean getSomeBean() {
  return new SomeBean("neil");  // set modelMap["attrib1"] = SomeBean("neil") on every request
}

@RequestMapping("/a")
void pathA(@ModelAttribute("attrib1") SomeBean someBean) {
  assertEquals("neil", someBean.getName());
}

GET /a

Utilisez @ModelAttribute (paramètre) pour obtenir un objet stocké dans un attribut flash:

@RequestMapping("/a")
String pathA(RedirectAttributes redirectAttributes) {
  redirectAttributes.addFlashAttribute("attrib1", new SomeBean("from flash"));
  return "redirect:/b";
}

@RequestMapping("/b")
void pathB(@ModelAttribute("attrib1") SomeBean someBean) {
  assertEquals("from flash", someBean.getName());
}

GET /a

Utilisez @ModelAttribute (paramètre) pour obtenir un objet stocké par @SessionAttributes

@Controller
@SessionAttributes("attrib1")
public class Controller1 {

    @RequestMapping("/a")
    void pathA(Model model) {
        model.addAttribute("attrib1", new SomeBean("neil")); //this ends up in session due to @SessionAttributes on controller
    }

    @RequestMapping("/b")
    void pathB(@ModelAttribute("attrib1") SomeBean someBean) {
        assertEquals("neil", someBean.getName());
    }
}

GET /a
GET /b

53
Neil McGuigan

Votre question semble avoir déjà reçu une réponse:

Qu'est-ce que @ModelAttribute dans Spring MVC?

Pour résumer la réponse et l'article de blog: quand vous voulez que votre objet de sauvegarde de formulaire (instance de Personne) soit persistant dans les demandes.

Sinon, sans l'annotation, la méthode de mappage de la requête supposera que Person est un nouvel objet et n'est en aucun cas lié à votre objet de sauvegarde de formulaire. Le billet de blog qui fait référence aux affiches est vraiment génial, à lire absolument.

2
abelito

Un @ModelAttribute sur un argument de méthode indique que l'argument sera extrait du modèle. S'il n'est pas présent dans le modèle, l'argument sera d'abord instancié, puis ajouté au modèle.

0
dhS