How to store data is session scope in Spring

2019-08-08 21:38发布

问题:

I have created two object in session scope like this @SessionAttributes({"userObj","simpleValue"}) in my controller.

I am adding a user object and String at these variables in my controller like this:

modelAndView.addObject("userObj", user);
modelAndView.addObject("simpleValue", "Hello World");

User class is a simple class with 2 properties id & name.

Lets say I created this in a controller called Controller1 which shows Page1. I can see the data of my session variables in page1.

Now I created another controller say Controller2 (this controller has no relation with page1 or Controller1) which displays page2, now in this new page I am able to access only the single session attribute for simpleValue, I am not able to access userObj, I am getting empty result.

As per the @SessionAttributes, it says:

NOTE: Session attributes as indicated using this annotation correspond to a specific handler's model attributes, getting transparently stored in a conversational session. Those attributes will be removed once the handler indicates completion of its conversational session. Therefore, use this facility for such conversational attributes which are supposed to be stored in the session temporarily during the course of a specific handler's conversation.

So I have 2 questions here:

1) I am not able to understand why Spring allowing me to access the simple property but not the User object in page2.

2) The document also says we have to use either traditional session or WebRequest. I able to use the sessison and access the variables, but can someone please help me how to use WebRequest for storing objects in session?

This is the code that I am using:

Controller1.java

@Controller
@SessionAttributes({"mySessionAttr","userObj"})
public class Controller1 {

    @RequestMapping(value="/page1")
    public ModelAndView singleFieldPage() {
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("mySessionAttr", "Hello World");
        modelAndView.addObject("userObj", new User(1,"Scott"));
        modelAndView.setViewName("page1");
        return modelAndView;
    }
}

Controller2.java

@Controller
public class Controller2 {

    @RequestMapping(value="/page2")
    public ModelAndView singleFieldPage(HttpSession session) {
        return new ModelAndView("page2");
    }   
}

page1.jsp & page2.jsp, both have same code.

<p>Session variable : ${simpleValue}</p>
<p>Product's name is ${userObj.name}. The id is ${userObj.id}

This is my User.java:

public class User {

private int id;
private String name;

public User() {
}

public User(int id, String name) {
    this.id = id;
    this.name = name;
}

   // Setters & Getters
}

This is my configuration files:

Spring based configuration

@Configuration
@ComponentScan("com.examples")
@EnableWebMvc
public class WebAppConfig {

    @Bean
    public UrlBasedViewResolver setupViewResolver() {
        UrlBasedViewResolver resolver = new UrlBasedViewResolver();
        resolver.setPrefix("/WEB-INF/pages/");
        resolver.setSuffix(".jsp");
        resolver.setViewClass(JstlView.class);
        return resolver;
    }

}

Web based configuration

public class Initializer implements WebApplicationInitializer {

    public void onStartup(ServletContext servletContext) throws ServletException {

        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(WebAppConfig.class);

        ctx.setServletContext(servletContext);  

        Dynamic servlet = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);

    }

}

回答1:

From my point of view the problem with the user object lies on the fact that the class User does not implementing Serializable.

And regarding the WebRequest, it is basically an abstraction for NativeWebRequest and AsyncWebRequest, as you can see at the documentation:

Generic interface for a web request. Mainly intended for generic web request interceptors, giving them access to general request metadata, not for actual handling of the request.

With that approach, WebRequestInterceptor may be used for Servlets as well as Portlets requests as states the documentation:

Interface for general web request interception. Allows for being applied to Servlet request as well as Portlet request environments, by building on the WebRequest abstraction.



回答2:

@SessionAttribute is tied to a single controller and as such the controller is also in charge of managing that session context. If you want conversations use web flow.

Originally posted by javadoc

Session attributes as indicated using this annotation correspond to a specific handler's model attributes, getting transparently stored in a conversational session. Those attributes will be removed once the handler indicates completion of its conversational session. Therefore, use this facility for such conversational attributes which are supposed to be stored in the session temporarily during the course of a specific handler's conversation.

Although the term conversation is used here it is basically the conversation with a single handler (controller in this case) and not over multiple handlers. For such cases and better control use Spring Web Flow.