Spring MVC3 @SessionAttributes和@ModelAttribute将自动从请求中获取值

时间:2014-08-25 04:00:22

标签: java spring session spring-mvc

我正在尝试开发一个Spring MVC应用程序,现在我遇到了一个问题。登录成功后,我将User实体添加到会话并调用http://localhost:8080/user以获取会话用户。这里一切都好。但是,如果我像这样调用http://localhost:8080/user?username=testuser这样的URL,那么会话用户的用户名将变为testuser。我该怎么办才能从会话中获取当前用户?

代码如下

实体:

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

控制器:

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

http://localhost:8080/user

的回复
[{"id":1,"username":"aaa111"}]

http://localhost:8080/user?username=testuser的回应;它应该与上面相同,但是

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

2 个答案:

答案 0 :(得分:5)

@SessionAttributes注释并非针对此目的。它的目的是在http请求期间在会话中存储对象。想象一下,一个冗长的数据库调用来检索你不想每次都检索这个对象但可能重用现有对象的对象。该对象旨在用作@ModelAttribute,此注释表示您要使用此对象进行绑定(即,您有一个表单来更改对象的属性)。完成对象的编辑后,您应该通过调用setComplete()对象上的SessionStatus来清除对象。另请参阅here

您希望在会话中存储对象并在需要时检索它。为此,请使用HttpSession以正常方式调用setAttributegetAttribute。要获取当前HttpSession,您只需添加类型HttpSession的方法参数,它就会为您注入。 (有关受支持的方法参数的列表,请参阅here。)

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

或者,由于您已经在使用Spring,因此可以使用WebUtils以方便使用。您可以使用getSessionAttributegetRequiredSessionAttribute方法从会话中获取值。

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

另一种解决方案是扩展Spring MVC。 Spring MVC使用HandlerMethodArgumentResolver来处理所有不同类型的方法参数。这种机制是可插拔的。您可以创建注释@CurrentUser并创建一个CurrentUserHandlerMethodArgumentResolver,它将从会话中检索用户并将其注入该位置。然后,您只需将当前用户添加到方法签名中即可。

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

配置自定义参数解析器

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

看起来你正在推销自己的安全框架,我建议不要这样做。相反,我建议改用Spring Security。这样做的好处是,它提供了与Servlet API的集成,允许通过自己动手(Principal)或仅添加类型request.getUserPrincipal()的方法参数来检索当前java.security.Principal。它还附带一个自定义HandlerMethodArgumentResolver,允许您获取当前的Spring Security Authentication对象。

答案 1 :(得分:0)

尝试从servlet请求获取控制器中的会话值,如下所示

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