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

杨家勇*_*杨家勇 3 java session spring spring-mvc

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

代码如下

实体:

@Entity
public class User {
    private Long id;
    private String username;
    // ...Getter and Setter...
}
Run Code Online (Sandbox Code Playgroud)

控制器:

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

回应 http://localhost:8080/user

[{"id":1,"username":"aaa111"}]
Run Code Online (Sandbox Code Playgroud)

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

[{"id":1,"username":"testuser"}]
Run Code Online (Sandbox Code Playgroud)

M. *_*num 5

@SessionAttributes注释不适用于这一点.它的目的是在http请求期间在会话中存储对象.想象一下,一个冗长的数据库调用来检索每次都不想检索此对象的对象,但可能会重用现有对象.该对象旨在用作a @ModelAttribute,此注释表示您要使用此对象进行绑定(即,您有一个表单来更改对象的属性).当你与对象的编辑完成后,您应该调用明确这一点setComplete()SessionStatus对象.另见这里.

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

public void myRequestHandlingMethod(HttpSession session) {
     User currentUser = (User) session.getAttribute("currentUser");
}
Run Code Online (Sandbox Code Playgroud)

或者,当您已经使用Spring时,您可以使用它WebUtils以方便使用.您可以使用getSessionAttributegetRequiredSessionAttribute方法从会话中获取值.

public void myRequestHandlingMethod(HttpServletRequest request) {
     User currentUser = (User) WebUtils.getSessionAttribute("currentUser", request)
}
Run Code Online (Sandbox Code Playgroud)

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

public void myRequestHandlingMethod(@CurrentUser User user) { ... }
Run Code Online (Sandbox Code Playgroud)

配置自定义参数解析程序

<mvc:annotation-driven>
     <mvc:argument-resolvers>
          <bean class="com.yourcomponany.app.web.CurrentUserHandlerMethodArgumentResolver />
     </mvc:argument-resolvers>
</mvc:annotation-driven>
Run Code Online (Sandbox Code Playgroud)

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