1. 利用@SessionAttribute进行获取
这是最简单直接的方法,可以直接在方法的参数中直接进行注入,如下:
// 可以直接从Session中抓取域对象
public Account login(@SessionAttribute Account account) {
return account;
}
上面的方法虽然简单,但是唯一的缺点是Spring Framework 4.3之前的版本不支持。
2. 利用@SessionAttributes进行获取
与@SessionAttribute不同的是,@SessionAttributes不仅多了一个复数“s”,而且从Spring Framework 2.5版本就开始支持,此外@SessionAttributes还必须注解在类上,这样类里面的所有方法就可以直接通过@ModelAttribute获取域对象,所以总结起来,@SessionAttributes抓取域对象分为两步;
1. 在类上添加注解@SessionAttributes;
2. 在方法的参数中通过@ModelAttribute获取域对象;
@RestController
@SessionAttributes("account")
public class SecurityContextController {
@RequestMapping("/account")
public Account login(@ModelAttribute("account") Account account) {
return account;
}
}
此外,我们不妨把@SessionAttributes的官方说明重读一遍,以了解它的真正含义,如下:
This will typically list the names of model attributes
which should be transparently stored in the session or some conversational storage,
serving as form-backing beans.
Declared at the type level,
applying to the model attributes that the annotated handler class operates on.
大概意思是@SessionAttributes会列出存储在Session或会话中的域对象,就像表单的后台对象一样提供服务,并且必须注解在类型上,并应用于此类的域对象上。
3. 直接通过Session获取
这个更简单,直接通过HttpSession获取,但需要更多的类型判断与转换代码,如下:
@RequestMapping("/account")
public Account account(HttpSession session) {
Object obj = session.getAttribute("account");
if(obj instanceof Account) {
Account account = (Account) obj;
return account;
}
return null;
}
为了简化Session的调用,充分利用@ModelAttribute方法的初始化特性,我们还可以改进为如下的形式:
public class SecurityContextController {
ThreadLocal<Account> authContext = new ThreadLocal<>();
// 此方法会在每次请求前调用(这个类的处理方法)
@ModelAttribute
public void initUser(HttpSession session) {
Object obj = session.getAttribute("account");
if(obj instanceof Account) {
Account user = (Account) obj;
authContext.set(user);
}
}
// 现在可直接使用存储的属性
@RequestMapping("/getUser")
public AegisUser get() {
return authContext.get();
}
}
结论
在Spring Boot中,从Session中获取域对象还是比较容易的,唯一可能引起误解或较难使用的只有@SessionAttributes,一定要记住它的二个使用步骤。