How to use Session attributes in Spring-mvc
Solution 1
If you want to delete object after each response you don't need session,
If you want keep object during user session , There are some ways:
-
directly add one attribute to session:
@RequestMapping(method = RequestMethod.GET) public String testMestod(HttpServletRequest request){ ShoppingCart cart = (ShoppingCart)request.getSession().setAttribute("cart",value); return "testJsp"; }
and you can get it from controller like this :
ShoppingCart cart = (ShoppingCart)session.getAttribute("cart");
-
Make your controller session scoped
@Controller @Scope("session")
-
Scope the Objects ,for example you have user object that should be in session every time:
@Component @Scope("session") public class User { String user; /* setter getter*/ }
then inject class in each controller that you want
@Autowired private User user
that keeps class on session.
-
The AOP proxy injection : in spring -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>
then inject class in each controller that you want
@Autowired private User user
5.Pass HttpSession to method:
String index(HttpSession session) {
session.setAttribute("mySessionAttribute", "someValue");
return "index";
}
6.Make ModelAttribute in session By @SessionAttributes("ShoppingCart"):
public String index (@ModelAttribute("ShoppingCart") ShoppingCart shoppingCart, SessionStatus sessionStatus) {
//Spring V4
//you can modify session status by sessionStatus.setComplete();
}
or you can add Model To entire Controller Class like,
@Controller
@SessionAttributes("ShoppingCart")
@RequestMapping("/req")
public class MYController {
@ModelAttribute("ShoppingCart")
public Visitor getShopCart (....) {
return new ShoppingCart(....); //get From DB Or Session
}
}
each one has advantage and disadvantage:
@session may use more memory in cloud systems it copies session to all nodes, and direct method (1 and 5) has messy approach, it is not good to unit test.
To access session jsp
<%=session.getAttribute("ShoppingCart.prop")%>
in Jstl :
<c:out value="${sessionScope.ShoppingCart.prop}"/>
in Thymeleaf:
<p th:text="${session.ShoppingCart.prop}" th:unless="${session == null}"> . </p>
Solution 2
Use @SessionAttributes
See the docs: Using @SessionAttributes to store model attributes in the HTTP session between requests
"Understanding Spring MVC Model And Session Attributes" also gives a very good overview of Spring MVC sessions and explains how/when @ModelAttribute
s are transferred into the session (if the controller is @SessionAttributes
annotated).
That article also explains that it is better to use @SessionAttributes
on the model instead of setting attributes directly on the HttpSession because that helps Spring MVC to be view-agnostic.
Solution 3
SessionAttribute
annotation is the simplest and straight forward instead of getting session from request object and setting attribute.
Any object can be added to the model in controller and it will stored in session if its name matches with the argument in @SessionAttributes
annotation.
In below eg, personObj
will be available in 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;
}
}
Solution 4
The below annotated code would set "value" to "name"
@RequestMapping("/testing")
@Controller
public class TestController {
@RequestMapping(method = RequestMethod.GET)
public String testMestod(HttpServletRequest request){
request.getSession().setAttribute("name", "value");
return "testJsp";
}
}
To access the same in JSP use
${sessionScope.name}
.
For the @ModelAttribute
see this link
Solution 5
Isn't it easiest and shortest that way? I knew it and just tested it - working perfect here:
@GetMapping
public String hello(HttpSession session) {
session.setAttribute("name","value");
return "hello";
}
p.s. I came here searching for an answer of "How to use Session attributes in Spring-mvc", but read so many without seeing the most obvious that I had written in my code. I didn't see it, so I thought its wrong, but no it was not. So lets share that knowledge with the easiest solution for the main question.
Related videos on Youtube
gstackoverflow
Updated on December 25, 2020Comments
-
gstackoverflow over 3 years
Could you help me write spring mvc style analog of this code?
session.setAttribute("name","value");
And how to add an element that is annotated by
@ModelAttribute
annotation to session and then get access to it? -
Akah almost 8 yearssessions work just for requests within the same controller instance. What if control needs to be sent to another controller, this session will be destroyed and a new one created if necessary.
-
Vadim Kolesnikov almost 8 years3. If your controller is singleton then you need to definition proxyMode = ScopedProxyMode.TARGET_CLASS for injected component with session scope. @Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
-
Yura over 7 years@larrytech how could it be? I think you have just forgotten to add SessionAttributes to your second controller
-
chris about 7 yearsMaking the controller session scoped is the worst option here, even though it looks simple and easy to use at first. But if you want to scale your application out some time in the future, you'll be running into trouble as you will probably be needing a distributed session store such as Redis (unless you use sticky sessions, sacrificing availability for convenience). Thus, session-scoped beans should generally be dumb serializable POJOs. This way you are prepared for scale-out in case the need arises.
-
Shessuky over 4 yearsYou're right ! that's what I was thinking since you can acess all Http object that we need directly when you declare them in Controller methods (GET/POST request)