Struts2中SessionAware获取Session值始终为Null的问题排查
确认两个Action都正确实现SessionAware接口
两个Action都必须实现SessionAware,并且重写setSession(Map<String, Object> session)方法,同时正确将Struts注入的session赋值给类成员变量。比如:// 正确的实现示例 public class MainAction implements SessionAware { private Map<String, Object> session; @Override public void setSession(Map<String, Object> session) { this.session = session; // 必须完成赋值,否则成员变量为null } public String execute() { UserObject user = new UserObject(); session.put("CURRENT_USER", user); // 存入Session return SUCCESS; } }要是UploadAction的
setSession方法参数写错(比如写成HttpSession),或者没给成员变量赋值,那session本身就是null,自然取不出对象。检查Session键名是否完全一致
Session的键名是大小写敏感的!存的时候用"CURRENT_USER",取的时候就不能写成"current_user"或者"CurrentUser"。比如UploadAction里的错误写法:// 错误:键名大小写不匹配 UserObject user = (UserObject) session.get("current_user");必须和存入时的键名完全一致才能取到对象。
确认两个请求属于同一个会话
检查两次请求的JSESSIONID是否相同:可以在浏览器开发者工具的Cookie里查看JSESSIONID的值,或者在Action里打印session.get("javax.servlet.http.session.id")的输出结果。如果两次值不一样,说明是两个独立会话(比如开了无痕窗口、浏览器禁用Cookie,或者服务器配置了会话隔离),这种情况下自然拿不到之前存的对象。UserObject必须实现Serializable接口
Session中的对象需要支持序列化(尤其是服务器有集群、会话持久化的场景),如果UserObject没实现Serializable,可能会导致对象无法正常存储到Session,跨Action时丢失。比如:// 正确:实现Serializable接口 public class UserObject implements Serializable { // 类成员属性与方法... }检查Action的拦截器栈配置
如果自定义了Action的拦截器栈,必须确保包含Struts2的默认拦截器栈(defaultStack),因为SessionAware的依赖注入是由默认栈里的拦截器处理的。比如struts.xml里的错误配置:<!-- 错误:自定义拦截器栈未包含defaultStack --> <action name="upload" class="com.example.UploadAction"> <interceptor-ref name="myCustomStack"/> <result name="success">/upload.jsp</result> </action>正确的配置应该是:
<action name="upload" class="com.example.UploadAction"> <interceptor-ref name="myCustomStack"/> <interceptor-ref name="defaultStack"/> <!-- 必须添加默认栈 --> <result name="success">/upload.jsp</result> </action>
内容的提问来源于stack exchange,提问作者Bug

