Jak używać atrybutów sesji w Spring-mvc

108

Czy możesz mi pomóc napisać analogowy analog w stylu MVC dla tego kodu?

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

A jak dodać @ModelAttributedo sesji element opatrzony adnotacją, a następnie uzyskać do niego dostęp?

gstackoverflow
źródło

Odpowiedzi:

185

Jeśli chcesz usunąć obiekt po każdej odpowiedzi, nie potrzebujesz sesji,

Jeśli chcesz zachować obiekt podczas sesji użytkownika, jest kilka sposobów:

  1. bezpośrednio dodaj jeden atrybut do sesji:

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

    i możesz go pobrać z kontrolera w ten sposób:

    ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
  2. Ustaw zakres sesji kontrolera

    @Controller
    @Scope("session")
  3. Zakres obiektów, na przykład masz obiekt użytkownika, który powinien być w sesji za każdym razem:

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

    następnie wstrzyknij klasę do każdego kontrolera, który chcesz

       @Autowired
       private User user

    który utrzymuje zajęcia na sesji.

  4. Wstrzyknięcie proxy AOP: wiosną -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>

    następnie wstrzyknij klasę do każdego kontrolera, który chcesz

    @Autowired
    private User user

5.Pass HttpSession do metody:

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

6. Stwórz ModelAttribute w sesji przez @SessionAttributes ("ShoppingCart"):

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

lub możesz dodać Model do całej klasy kontrolera, np.

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

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

każdy ma zalety i wady:

@session może zużywać więcej pamięci w systemach chmurowych, kopiuje sesję do wszystkich węzłów, a metoda bezpośrednia (1 i 5) ma niechlujne podejście, test jednostkowy nie jest dobry.

Aby uzyskać dostęp do sesji jsp

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

w Jstl:

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

w Thymeleaf:

<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>
Ali.Mojtehedy
źródło
6
3. Jeśli twój kontroler jest singletonem, musisz zdefiniować proxyMode = ScopedProxyMode.TARGET_CLASS dla wstrzykniętego komponentu z zakresem sesji. @Scope (value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
Vadim Kolesnikov
1
Ustawienie zakresu sesji kontrolera jest tutaj najgorszą opcją, mimo że na początku wygląda to na proste i łatwe w użyciu. Ale jeśli zechcesz w przyszłości skalować swoją aplikację, napotkasz problemy, ponieważ prawdopodobnie będziesz potrzebować rozproszonego magazynu sesji, takiego jak Redis (chyba że używasz sesji lepkich, poświęcając dostępność dla wygody). Zatem fasola o zasięgu sesji powinna być generalnie głupimi obiektami POJO, które można serializować. W ten sposób jesteś przygotowany na skalowanie w poziomie w razie potrzeby.
chris
A co z RequestContextHolder?
user1589188
Wstrzyknięcie Userziarna zadziała tylko wtedy, gdy wywołujesz ziarno w klasie, która jest również sessionobjęta zakresem, w przeciwnym razie, jeśli nie ma sesji, zgłasza wyjątek, ponieważ nie byłoby żadnej aktywnej sesji w kontekście @runtime, gdy wstrzykniemy userziarno do innej klasy !!
Jose Mhlanga
41

Posługiwać się @SessionAttributes

Zobacz dokumentację: Używanie @SessionAttributes do przechowywania atrybutów modelu w sesji HTTP między żądaniami

Zrozumienie modelu Spring MVC i atrybutów sesji ” daje również bardzo dobry przegląd sesji Spring MVC i wyjaśnia, w jaki sposób / kiedy @ModelAttributesą przenoszone do sesji (jeśli kontroler jest @SessionAttributesopatrzony adnotacją).

W tym artykule wyjaśniono również, że lepiej jest używać @SessionAttributesmodelu zamiast ustawiać atrybuty bezpośrednio w HttpSession, ponieważ pomaga to Spring MVC być niezależnym od widoku.

Filtr Heinricha
źródło
Jak można wykorzystać sessionAttributes do przesyłania obiektów między kontrolerami?
larrytech
27

SessionAttributeadnotacja jest najprostszą i najprostszą metodą zamiast pobierania sesji z obiektu żądania i atrybutu ustawienia. Dowolny obiekt można dodać do modelu w kontrolerze i będzie on przechowywany w sesji, jeśli jego nazwa będzie zgodna z argumentem w @SessionAttributesadnotacji. Poniżej np. personObjBędzie dostępny w sesji.

@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
źródło
sesje działają tylko dla żądań w ramach tej samej instancji kontrolera. Co jeśli kontrola musi zostać przesłana do innego kontrolera, ta sesja zostanie zniszczona iw razie potrzeby utworzona nowa.
larrytech
1
@larrytech, jak to możliwe? Myślę, że właśnie zapomniałeś dodać SessionAttributes do swojego drugiego kontrolera
Yura
19

Poniższy kod z adnotacjami ustawiłby „wartość” na „nazwa”

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

Aby uzyskać dostęp do tego samego w JSP użyj ${sessionScope.name}.

Aby @ModelAttributezobaczyć ten odnośnik

aksappy
źródło
4

Czy nie jest to najłatwiejsze i najkrótsze w ten sposób? Wiedziałem i właśnie to przetestowałem - tutaj działa idealnie:

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

ps Przyszedłem tutaj, szukając odpowiedzi „ Jak używać atrybutów sesji w Spring-mvc ”, ale przeczytałem tak wiele, nie widząc najbardziej oczywistego, który napisałem w swoim kodzie. Nie widziałem tego, więc pomyślałem, że to źle, ale nie, nie było. Podzielmy się więc tą wiedzą z najłatwiejszym rozwiązaniem głównego pytania.

strash
źródło
1
Masz rację ! właśnie o tym myślałem, ponieważ możesz uzyskać dostęp do wszystkich obiektów HTTP, których potrzebujemy bezpośrednio, gdy deklarujesz je w metodach kontrolera (żądanie GET / POST)
Shessuky,
1

Spróbuj tego...

@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 Indie
źródło
0

Kiedy próbowałem zalogować się (który jest modalny bootstrap), użyłem adnotacji @sessionattributes. Problem polegał jednak na tym, że widok jest przekierowaniem („redirect: / home”), wartości, które wprowadziłem do sesji, są wyświetlane w adresie URL. Niektóre źródła internetowe sugerują śledzenie http://docs.spring.io/spring/docs/4.3.x/spring-framework-reference/htmlsingle/#mvc-redirecting Ale zamiast tego użyłem HttpSession. Ta sesja będzie dostępna do momentu zamknięcia przeglądarek. Oto przykładowy kod

        @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
}

Nie zmieniasz konkretnej rzeczy po stronie widoku.

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

Po zalogowaniu dodaj powyższe kody w dowolnym miejscu na swojej stronie internetowej. Jeśli sesja jest ustawiona poprawnie, zobaczysz tam wartości. Upewnij się, że poprawnie dodałeś tagi jstl i wyrażenia El- (tutaj jest link do ustawiania tagów jstl https://menukablog.wordpress.com/2016/05/10/add-jstl-tab-library-to-you-project- poprawnie / )

Menuka Ishan
źródło
0

Użyj Ta metoda jest bardzo prosta i łatwa w użyciu

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

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

w jsp raz użyj, a następnie usuń

<c:remove var="errorMsg" scope="session"/>      
Bacha
źródło
0

Wiosną 4 Web MVC. Możesz użyć @SessionAttributew metodzie z @SessionAttributesna poziomie kontrolera

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

    GetMapping("/showOrder")
    public String showPage(@SessionAttribute("SessionKey") SearchCriteria searchCriteria) {
     // method body
}
sendon1982
źródło