简体   繁体   中英

Spring MVC3 @SessionAttributes and @ModelAttribute will automatically get value from request

I'm trying to develop a Spring MVC application, now I encounter a question. When login successful I add the User entity to session and call http://localhost:8080/user to get the session user. Everything is OK here. But if I call the URL like this http://localhost:8080/user?username=testuser then the session user's username will change to testuser. What should I do that just get current user from session?

The code likes below

Entity:

@Entity
public class User {
    private Long id;
    private String username;
    // ...Getter and Setter...
}

Controller:

@Controller
@RequestMapping("user")
@SessionAttributes("current_user")
public class UserController {
    @RequestMapping(method=RequestMethod.GET)
    @ResponseBody
    public User testSession(@ModelAttribute("current_user") User user) {
        return user;
    }
}

Response of http://localhost:8080/user

[{"id":1,"username":"aaa111"}]

Response of http://localhost:8080/user?username=testuser ; it should be same as above, but is

[{"id":1,"username":"testuser"}]

The @SessionAttributes annotation isn't intended for this. Its intend is to store objects in the session during http requests. Imagine a lengthy database call to retrieve an object you don't want to retrieve this object each time but probably reuse an existing one. The object is to be intended to be used as a @ModelAttribute , this annotation indicates that you want to use this object for binding (ie you have a form to change attributes of the object). When you are finished with the editing of the object you should make this clear by calling setComplete() on the SessionStatus object. See also here .

You want to store an object in the session and retrieve it when you need it. For this use the HttpSession in the normal way of calling setAttribute and getAttribute . To obtain the current HttpSession you can simply add a method argument of the type HttpSession and it will be injected for you. (See here for a list of supported method arguments).

public void myRequestHandlingMethod(HttpSession session) {
     User currentUser = (User) session.getAttribute("currentUser");
}

Or as you are already using Spring you could use the WebUtils for convenience. You can use the getSessionAttribute or getRequiredSessionAttribute methods to obtain the value from the session.

public void myRequestHandlingMethod(HttpServletRequest request) {
     User currentUser = (User) WebUtils.getSessionAttribute("currentUser", request)
}

Another solution would be to extend Spring MVC. Spring MVC uses a HandlerMethodArgumentResolver to handle all the different types of method arguments. This mechanism is pluggable. You could create an annotation @CurrentUser and create a CurrentUserHandlerMethodArgumentResolver that will retrieve the user from the session and injects it in that place. You could then simply add your current user to your method signature.

public void myRequestHandlingMethod(@CurrentUser User user) { ... }

Configure the custom argument resolver

<mvc:annotation-driven>
     <mvc:argument-resolvers>
          <bean class="com.yourcomponany.app.web.CurrentUserHandlerMethodArgumentResolver />
     </mvc:argument-resolvers>
</mvc:annotation-driven>

It also looks like you are rolling your own security framework, which I would advice against. Instead I would suggest using Spring Security instead. Advantage of this is that this provides integration with the Servlet API allowing for retrieval of the current Principal by either doing it yourself ( request.getUserPrincipal() ) or simply adding a method argument of the type java.security.Principal . It also comes with a custom HandlerMethodArgumentResolver which allows you to obtain the current Spring Security Authentication object.

try to get session value in controller from servlet request like below

@Controller
@RequestMapping("user")
@SessionAttributes("current_user")
public class UserController{
    @RequestMapping(method=RequestMethod.GET)
    @ResponseBody
    public User testSession(HttpServletRequest request){
        //false means do not create new session
        HttpSession session = request.getSession(false);
        return session != null?session.getAttribute("current_user"):null;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM