web-dev-qa-db-fra.com

Spring Framework 3 et attributs de session

J'ai un objet de formulaire que je règle à demander dans le gestionnaire de demandes GET dans mon contrôleur Spring. La première fois que l'utilisateur entre dans la page, un nouvel objet de formulaire doit être créé et configuré pour demander. Si l'utilisateur envoie un formulaire, l'objet formulaire est renseigné à partir de la demande et maintenant, l'objet formulaire possède tous les attributs de l'utilisateur. Ensuite, le formulaire est validé et si la validation est correcte, le formulaire est enregistré dans la base de données. Si le formulaire n'est pas validé, je souhaite enregistrer un objet de formulaire en session, puis le rediriger vers la page de traitement des demandes GET. Lorsque la demande est redirigée vers le gestionnaire GET, elle doit vérifier si la session contient un objet de formulaire.

J'ai découvert qu'il y avait une annotation @SessionAttributes ("form") dans Spring, mais pour une raison quelconque, le fait que cela ne fonctionne pas car, pour la première fois, la forme de l'attribut de session est nulle et donne une erreur:

org.springframework.web.HttpSessionRequiredException: Session attribute 'form' required - not found in session

Voici mon contrôleur:

@RequestMapping(value="form", method=RequestMethod.GET)
public ModelAndView viewForm(@ModelAttribute("form") Form form) {
    ModelAndView mav = new ModelAndView("form");      
    if(form == null) form = new Form();
    mav.addObject("form", form);
    return mav;
}

@RequestMapping(value="form", method=RequestMethod.POST)
@Transactional(readOnly = true)
public ModelAndView saveForm(@ModelAttribute("form") Form form) {
    FormUtils.populate(form, request);
    if(form.validate())
    {
        formDao.save();         
    }
    else 
    {
        return viewForm(form);
    }
    return null;
}
22
newbie

Le travail de @SessionAttribute consiste à lier un objet de modèle existant à la session. S'il n'existe pas encore, vous devez le définir. C'est déroutant, à mon avis, mais essayez quelque chose comme ça:

@SessionAttributes({"form"})
@Controller
public class MyController {

   @RequestMapping(value="form", method=RequestMethod.GET)
   public ModelAndView viewForm(@ModelAttribute("form") Form form) {
       ModelAndView mav = new ModelAndView("form");      
       if(form == null) form = new Form();
       mav.addObject("form", form);
       return mav;
   }

   @RequestMapping(value="form", method=RequestMethod.POST)
   @Transactional(readOnly = true)
   public ModelAndView saveForm(@ModelAttribute("form") Form form) {
      // ..etc etc
   }
}

Notez que le @SessionAttributes est déclaré sur la classe plutôt que sur la méthode. Vous pouvez mettre où vous voulez, vraiment, mais je pense que c'est plus logique pour la classe.

La documentation à ce sujet pourrait être beaucoup plus claire, à mon avis.

25
skaffman

Il lève Exception si le contrôleur appelle la première fois, bien que @SessionAttributes ({"form"}) ait été ajouté à la classe Donc, ajouter la méthode suivante populateForm résoudra ce problème.

@SessionAttributes({"form"})
@Controller
public class MyController {

   @ModelAttribute("form")
   public Form populateForm() {
       return new Form(); // populates form for the first time if its null
   }

   @RequestMapping(value="form", method=RequestMethod.GET)
   public ModelAndView viewForm(@ModelAttribute("form") Form form) {
       ModelAndView mav = new ModelAndView("form");      
       if(form == null) form = new Form();
       mav.addObject("form", form);
       return mav;
   }

   @RequestMapping(value="form", method=RequestMethod.POST)
   @Transactional(readOnly = true)
   public ModelAndView saveForm(@ModelAttribute("form") Form form) {
      // ..etc etc
   }
}
32
digz6666

s'il n'y a pas d'objet de session défini, je pense que ça va être comme ça:

@SessionAttributes({"form"})
    @Controller
    public class MyController {
   @RequestMapping(value="form", method=RequestMethod.GET)
   public ModelAndView viewForm() {
       ModelAndView mav = new ModelAndView("form");      
       if(form == null) form = new Form();
       mav.addObject("form", form);
       return mav;
   }

   @RequestMapping(value="form", method=RequestMethod.POST)
   @Transactional(readOnly = true)
   public ModelAndView saveForm(@ModelAttribute("form") Form form) {
      // ..etc etc
   }
}
1
Muhammad Ramahy
@Controller
@SessionAttributes("goal")
public class GoalController {

    @RequestMapping(value = "/addGoal", method = RequestMethod.GET)
    public String addGoal(Model model) {
        model.addAttribute("goal", new Goal(11));
        return "addGoal";
    }

    @RequestMapping(value = "/addGoal", method = RequestMethod.POST)
    public String addGoalMinutes(@ModelAttribute("goal") Goal goal) {
        System.out.println("goal minutes " + goal.getMinutes());
        return "addMinutes";
    }
}

Sur la page addGoal.jsp utilisateur entre n'importe quel montant et soumet la page. Le montant publié est stocké dans la session HTTP à cause de 

@ModelAttribute("goal") Goal goal

et

@SessionAttributes ("objectif")

Sans @ModelAttribute ("objectif"), la quantité entrée par l'utilisateur sur la page addGoal serait perdue

1

Je me bats aussi avec ça. J'ai lu ce post et cela a clarifié certaines choses:

Set session variable spring mvc 3

Autant que je sache, ceci dit essentiellement:

  • that Spring place les objets spécifiés par @SessionAttributes dans la session uniquement pendant la durée comprise entre la première demande GET et la demande POST qui la suit. Après cela, l'objet est supprimé de la session. Je l'ai essayé dans une petite application et il a approuvé la déclaration.

Par conséquent, si vous souhaitez que les objets durent plus longtemps au cours de plusieurs requêtes GET et POST, vous devez les ajouter manuellement à la session HttpSession, comme d'habitude.

0
matthaeus