Comment utiliser les attributs de session dans Spring-mvc

108

Pourriez-vous m'aider à écrire l'analogue de style mvc à ressort de ce code?

 session.setAttribute("name","value");

Et comment ajouter un élément annoté par @ModelAttributeannotation à la session, puis y accéder?

gstackoverflow
la source

Réponses:

185

Si vous souhaitez supprimer un objet après chaque réponse, vous n'avez pas besoin de session,

Si vous souhaitez conserver l'objet pendant la session utilisateur, il existe plusieurs moyens:

  1. ajoutez directement un attribut à la session:

    @RequestMapping(method = RequestMethod.GET)
    public String testMestod(HttpServletRequest request){
       ShoppingCart cart = (ShoppingCart)request.getSession().setAttribute("cart",value);
       return "testJsp";
    }

    et vous pouvez l'obtenir du contrôleur comme ceci:

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
  2. Rendre votre session de contrôleur limitée

    @Controller
    @Scope("session")
  3. Portez les objets, par exemple, vous avez un objet utilisateur qui devrait être en session à chaque fois:

    @Component
    @Scope("session")
    public class User
     {
        String user;
        /*  setter getter*/
      }

    puis injectez la classe dans chaque contrôleur que vous voulez

       @Autowired
       private User user

    qui garde la classe en session.

  4. L'injection de proxy AOP: au printemps -xml:

    <beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:aop="http://www.springframework.org/schema/aop"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
    
      <bean id="user"    class="com.User" scope="session">     
          <aop:scoped-proxy/>
      </bean>
    </beans>

    puis injectez la classe dans chaque contrôleur que vous voulez

    @Autowired
    private User user

5.Passez HttpSession à la méthode:

 String index(HttpSession session) {
            session.setAttribute("mySessionAttribute", "someValue");
            return "index";
        }

6.Faites ModelAttribute en session par @SessionAttributes ("ShoppingCart"):

  public String index (@ModelAttribute("ShoppingCart") ShoppingCart shoppingCart, SessionStatus sessionStatus) {
//Spring V4
//you can modify session status  by sessionStatus.setComplete();
}

ou vous pouvez ajouter un modèle à toute la classe de contrôleur comme,

@Controller
    @SessionAttributes("ShoppingCart")
    @RequestMapping("/req")
    public class MYController {

        @ModelAttribute("ShoppingCart")
        public Visitor getShopCart (....) {
            return new ShoppingCart(....); //get From DB Or Session
        }  
      }

chacun a un avantage et un inconvénient:

@session peut utiliser plus de mémoire dans les systèmes cloud, il copie la session sur tous les nœuds, et la méthode directe (1 et 5) a une approche désordonnée, il n'est pas bon de tester unitaire.

Pour accéder à la session jsp

<%=session.getAttribute("ShoppingCart.prop")%>

dans Jstl:

<c:out value="${sessionScope.ShoppingCart.prop}"/>

dans Thymeleaf:

<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>
Ali.Mojtehedy
la source
6
3. Si votre contrôleur est singleton, vous devez définir proxyMode = ScopedProxyMode.TARGET_CLASS pour le composant injecté avec la portée de session. @Scope (value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
Vadim Kolesnikov
1
Rendre la session du contrôleur cadrée est la pire option ici, même si cela semble simple et facile à utiliser au début. Mais si vous souhaitez faire évoluer votre application dans le futur, vous rencontrerez des problèmes car vous aurez probablement besoin d'un magasin de session distribué tel que Redis (sauf si vous utilisez des sessions persistantes, sacrifiant la disponibilité pour plus de commodité). Ainsi, les beans de session doivent généralement être des POJO sérialisables stupides. De cette façon, vous êtes prêt à évoluer en cas de besoin.
chris
Qu'en est-il de RequestContextHolder?
user1589188
L'injection du Userbean ne fonctionnera que si vous appelez le bean dans une classe qui est également sessionportée, sinon si aucune session n'existe, alors elle lève une exception car il n'y aurait pas de session active dans le contexte @runtime lorsque nous injectons le userbean dans une autre classe !!
Jose Mhlanga
41

Utilisation @SessionAttributes

Voir la documentation: Utilisation de @SessionAttributes pour stocker les attributs de modèle dans la session HTTP entre les requêtes

« Comprendre le modèle Spring MVC et les attributs de session » donne également un très bon aperçu des sessions Spring MVC et explique comment / quand les @ModelAttributes sont transférés dans la session (si le contrôleur est @SessionAttributesannoté).

Cet article explique également qu'il est préférable de l'utiliser @SessionAttributessur le modèle au lieu de définir des attributs directement sur HttpSession, car cela aide Spring MVC à être indépendant de la vue.

Filtre Heinrich
la source
Comment pouvez-vous tirer parti de sessionAttributes pour transférer des objets entre les contrôleurs?
larrytech
27

SessionAttributel'annotation est la plus simple et la plus directe au lieu d'obtenir une session à partir de l'objet de demande et de l'attribut de réglage. Tout objet peut être ajouté au modèle dans le contrôleur et il sera stocké en session si son nom correspond à l'argument dans l' @SessionAttributesannotation. En dessous par exemple, personObjsera disponible en session.

@Controller
@SessionAttributes("personObj")
public class PersonController {

    @RequestMapping(value="/person-form")
    public ModelAndView personPage() {
        return new ModelAndView("person-page", "person-entity", new Person());
    }

    @RequestMapping(value="/process-person")
    public ModelAndView processPerson(@ModelAttribute Person person) {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("person-result-page");

        modelAndView.addObject("pers", person);
        modelAndView.addObject("personObj", person);

        return modelAndView;
    }

}
Amar
la source
les sessions fonctionnent uniquement pour les demandes dans la même instance de contrôleur. Que faire si le contrôle doit être envoyé à un autre contrôleur, cette session sera détruite et une nouvelle sera créée si nécessaire.
larrytech
1
@larrytech comment cela pourrait-il être? Je pense que vous venez d'oublier d'ajouter SessionAttributes à votre deuxième contrôleur
Yura
19

Le code annoté ci-dessous définirait "valeur" sur "nom"

@RequestMapping("/testing")
@Controller
public class TestController {
@RequestMapping(method = RequestMethod.GET)
public String testMestod(HttpServletRequest request){
    request.getSession().setAttribute("name", "value");
    return "testJsp";
  }
}

Pour accéder à la même utilisation dans JSP ${sessionScope.name}.

Pour le @ModelAttributevoir ce lien

aksappy
la source
4

N'est-ce pas ainsi le plus simple et le plus court ? Je le savais et je l'ai juste testé - fonctionnant parfaitement ici:

@GetMapping
public String hello(HttpSession session) {
    session.setAttribute("name","value");
    return "hello";
}

ps Je suis venu ici à la recherche d'une réponse sur " Comment utiliser les attributs de session dans Spring-mvc ", mais j'en ai lu autant sans voir le plus évident que j'avais écrit dans mon code. Je ne l'ai pas vu, alors j'ai pensé que c'était faux, mais non, ce n'était pas le cas. Partageons donc ces connaissances avec la solution la plus simple pour la question principale.

frapper
la source
1
Vous avez raison ! c'est ce à quoi je pensais puisque vous pouvez accéder à tous les objets Http dont nous avons besoin directement lorsque vous les déclarez dans les méthodes Controller (requête GET / POST)
Shessuky
1

Essaye ça...

@Controller
@RequestMapping("/owners/{ownerId}/pets/{petId}/edit")
@SessionAttributes("pet")
public class EditPetForm {

    @ModelAttribute("types")

    public Collection<PetType> populatePetTypes() {
        return this.clinic.getPetTypes();
    }

    @RequestMapping(method = RequestMethod.POST)
    public String processSubmit(@ModelAttribute("pet") Pet pet, 
            BindingResult result, SessionStatus status) {
        new PetValidator().validate(pet, result);
        if (result.hasErrors()) {
            return "petForm";
        }else {
            this.clinic.storePet(pet);
            status.setComplete();
            return "redirect:owner.do?ownerId="
                + pet.getOwner().getId();
        }
    }
}
R Palanivel-Tamilnadu Inde
la source
0

Lorsque j'essaie de me connecter (qui est un modal bootstrap), j'ai utilisé l'annotation @sessionattributes. Mais le problème était lorsque la vue est une redirection ("redirect: / home"), les valeurs que j'ai entrées dans la session s'affichent dans l'url. Certaines sources Internet suggèrent de suivre http://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#mvc-redirecting Mais j'ai plutôt utilisé HttpSession. Cette session sera là jusqu'à ce que vous fermiez les navigateurs. Voici un exemple de code

        @RequestMapping(value = "/login")
        @ResponseBody
        public BooleanResponse login(HttpSession session,HttpServletRequest request){
            //HttpServletRequest used to take data to the controller
            String username = request.getParameter("username");
            String password = request.getParameter("password");

           //Here you set your values to the session
           session.setAttribute("username", username);
           session.setAttribute("email", email);

          //your code goes here
}

Vous ne changez pas de chose spécifique du côté de la vue.

<c:out value="${username}"></c:out>
<c:out value="${email}"></c:out>

Après la connexion, ajoutez les codes ci-dessus à n'importe quel endroit de votre site Web. Si la session est correctement définie, vous y verrez les valeurs. Assurez-vous d'avoir correctement ajouté les balises jstl et les expressions El- (Voici le lien pour définir les balises jstl https://menukablog.wordpress.com/2016/05/10/add-jstl-tab-library-to-you-project- correctement / )

Menuka Ishan
la source
0

Utilisez cette méthode très simple et facile à utiliser

HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getNativeRequest();

                                                            request.getSession().setAttribute("errorMsg", "your massage");

dans jsp une fois utiliser puis supprimer

<c:remove var="errorMsg" scope="session"/>      
Bachas
la source
0

Au printemps 4 Web MVC. Vous pouvez utiliser @SessionAttributedans la méthode avec @SessionAttributesau niveau du contrôleur

@Controller
@SessionAttributes("SessionKey")
public class OrderController extends BaseController {

    GetMapping("/showOrder")
    public String showPage(@SessionAttribute("SessionKey") SearchCriteria searchCriteria) {
     // method body
}
sendon1982
la source