2010-12-02 16 views
6

Imaginons un code comme celui-ci:@ModelAttribute dans un procédé

@RequestMapping(value="/users", method=RequestMethod.GET) 
public String list(Model model) { 
    ... 
} 

@InitBinder("user") 
public void initBinder(WebDataBinder binder) { 
    binder.setDisallowedFields("password"); // Don't allow user to override the value 
} 

@ModelAttribute("user") 
public User prepareUser(@RequestParam("username") String username){ 
    ... 
} 

@RequestMapping(value="/user/save", method=RequestMethod.POST) 
public String save(@ModelAttribute("user") User user, Model model) {   
    ... 
} 

J'utilise un liant d'initialisation afin d'éviter qu'un champ peut être binded et je marquer un procédé (prepareUser()) avec @ModelAttribute pour préparer mon objet Utilisateur avant qu'il ne soit lié. Donc, quand j'appelle/user/save initBinder() et prepareUser() sont exécutés.

J'ai défini "user" dans @InitBinder et @ModelAttribute afin que Spring-MVC puisse comprendre que ces méthodes doivent être appliquées avant d'exécuter une méthode avec @ModelAttribute ("user").

Le problème est que la méthode annotée avec @ModelAttribute ("user") est exécutée avant chaque méthode mappée de ce contrôleur. Par exemple si j'appelle/users prepareUser est exécuté avant la méthode list(). Comment puis-je faire que ce préparateur est seulement exécuté avant la méthode save() ayant toutes les méthodes dans le même contrôleur?

Merci

+0

Que fait réellement 'prepareUser'? – skaffman

+0

@skaffman il prend le nom d'utilisateur param et charge l'objet User de la base de données, donc toutes les données qui ne peuvent pas être liées (mot de passe par exemple) ne sont pas remplacées par des valeurs nulles quand elles sont persistantes après la liaison – Javi

Répondre

7

Ce n'est pas vraiment ce que @ModelAttribute est pour. Si vous l'utilisez comme paramètre de méthode, il place le paramètre annoté dans le modèle (ça va). Si vous le mettez dans une méthode, il est appelé à chaque fois pour fournir des données de référence auxquelles toutes les méthodes du contrôleur doivent avoir accès.

Si vous voulez prendre le contrôle de la construction de votre objet Utilisateur, vous avez plusieurs options. Les deux qui sont les plus évidentes pour moi sont:

  1. Utilisez votre méthode de initBinder pour ajouter un nouvel éditeur personnalisé (une classe de PropertyEditor) pour la construction d'objets utilisateur,
  2. Utilisez le conversion service in Spring 3 pour convertir les noms d'utilisateur de chaîne aux objets utilisateur.
+0

OK Je comprends que cela devrait être fait dans initbinder avec un éditeur de propriétés, mais je ne comprends pas quel est le véritable but des méthodes avec l'annotation @ModelAttribute. Pouvez-vous me donner un exemple pour son utilisation typique? Et aussi, Pourquoi une chaîne peut-elle être donnée comme valeur dans l'annotation (par exemple "user" dans @ModelAttribute ("user")) si elle est exécutée avant chaque méthode? – Javi

+1

@Javi De bonnes questions. Premièrement, je ne pense pas que cela doive être fait dans initbinder, c'est juste possible. Je préfère l'approche du service de conversion plus moderne. Une utilisation typique pour les méthodes annotées avec @ModelAttribute est pour les données de référence que toutes les méthodes d'un contrôleur nécessitent. Pour utiliser un animalerie à titre d'exemple, un contrôleur peut avoir des méthodes pour lister les animaux domestiques et regarder les animaux domestiques, mais ils ont tous besoin d'informations pour un menu Catégories ("Lapins", "Chiens", etc.). Cela vous évite d'avoir à répéter cela dans chaque méthode. – GaryF

+2

@Javi Quant à savoir pourquoi vous pouvez lui donner un nom, c'est que Spring peut placer l'objet retourné dans le modèle sous ce nom. L'exemple dans le manuel de printemps vaut le coup d'oeil: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-modelattrib – GaryF