2009-09-03 5 views
13

Dans quelles circonstances exactes @SessionAttributes est-il effacé? J'ai découvert un comportement déroutant en essayant d'utiliser deux modèles dans une page.Quand est-ce que @SessionAttributes dans SpringMVC est supprimé? (Avec l'exemple de code)

Quand je fais un EEG suivi d'un POST en utilisant ce contrôleur ...

@Controller 
@RequestMapping("/myPage*") 
@SessionAttributes(value = {"object1", "object2"}) 
public class MyController { 

    @RequestMapping(method = RequestMethod.GET) 
    public String get(Model model) { 
     model.addAttribute("object1", new Object1()); 
     model.addAttribute("object2", new Object2()); 
     return "myPage"; 
    } 

    @RequestMapping(method = RequestMethod.POST) 
    public String post(@ModelAttribute(value = "object1") Object1 object1) { 
     //do something with object1 
     return "myPage"; 
    } 
} 

... object2 est effacé du modèle. Il n'existe plus en tant que @SessionAttribute et n'est pas accessible sur ma page d'affichage.

Toutefois, si la signature de la deuxième méthode est modifiée à cette ...

public String post(@ModelAttribute(value = "object1") Object1 object1, 
        @ModelAttribute(value = "object2") Object2 object2) { 

... alors object2 ne sont pas effacés du modèle et est disponible sur ma page de vue.

Le javadoc pour @SessionAttributes dit:

... attributs seront enlevés une fois le gestionnaire indique la fin de sa session de conversation.

Mais je ne vois pas comment j'ai indiqué l'achèvement de la session conversationnelle dans le premier exemple, mais pas dans le second exemple. Est-ce que quelqu'un peut expliquer ce comportement ou est-ce un bug?

+0

Ce problème a été résolu au printemps 3.0RC1. Voir http://jira.springsource.org/browse/SPR-6084 Merci Juergen! –

Répondre

14

Vous indiquez la fin de la conversation en appelant

SessionStatus.setComplete

public void post(...., SessionStatus status) { 
    status.setComplete(); 
} 

Cela dit, je ne vois pas pourquoi vous devriez desserrez un attribut de modèle et non l'autre.

Avez-vous essayé de faire quelque chose comme:

@ModelAttribute("object1") 
public Object object1() { return new Object(); } 

@ModelAttribute("object2") 
public Object object2() { return new Object(); } 

Et voir comment cela se compare à mettre les attributs dans le modèle à la main.

+1

J'ai essayé votre suggestion - et étonnamment cela fonctionne! Maintenant, je suis vraiment confus. Pourquoi y a-t-il une différence à définir manuellement l'attribut de modèle et à le définir à l'aide de @ModelAttribute? –

+2

Hélas j'ai fait un boo-boo. De la référence (3.0.0.M3): "Remarque: les méthodes annotées @ModelAttribute seront exécutées avant la méthode de gestionnaire annotée @RequestMapping choisie". La raison qui fonctionne est donc que les méthodes object1 et object2 sont exécutées avant les méthodes get et post. Cela peut effectivement être ce que vous voulez, mais je ne le soupçonne pas. – ptomli

+0

Oui, j'ai réalisé que juste après avoir posté mon commentaire. Je pourrais soulever ceci avec le ressort car je ne vois aucune explication raisonnable pour ce comportement. –

1

Vous pouvez supprimer ModelAttribute niveau de la session unique comme celui-ci:

Compte tenu ModelMap model, HttpSession session et vous faire:

if (categoryId != null) 
    model.addAttribute("categoryId", categoryId); 
else { 
    model.remove("categoryId"); 
    session.removeAttribute("categoryId"); 
} 
Questions connexes