setAttribute:非可序列化属性(Java对象序列化)

5

我们刚刚切换到Glassfish V2。在设置会话属性时,我们现在遇到了错误。

错误信息如下:

java.lang.IllegalArgumentException: PWC2788: setAttribute: Non-serializable attribute

代码是:

getRequest().getSession().setAttribute("questionsForUser", getQuestions());

getQuestions()是一个简单的getter,位于名为“Parent Action”的抽象类中...所以要使getQuestions()成为可序列化对象,我的类需要实现Serializable吗?

public List getQuestions() {
    return questions;
}
  • 我们如何使这个对象可序列化?
  • 只将序列化的对象放入会话中是否是一个好的实践方法(因为Glassfish似乎要求这样做)?
  • 会话中序列化对象被交换到其他用户是否存在风险?

编辑:我正在使用ORM(iBatis)

有关“问题”的更多信息:

setter:

public void setQuestions(List questions) {
    this.questions = questions;
}

在这个方法中调用setter。该方法调用iBatis映射。

public void prepareQuestions()
{        
setExamIfaceDAO((SecurityExamIfaceDAO)ApplicationInitializer.getApplicationContext().getBean("securityExamIfaceDAO"));
    String userRole = questionsBasedOnUserRole();
    int questionsToBeShown = 0;
    if (userRole.equalsIgnoreCase("C"))
        questionsToBeShown = 15;
    else if (userRole.equalsIgnoreCase("U"))
        questionsToBeShown = 10;
    List local_questions = getExamIfaceDAO().getSecurityQuestions(userRole);
    Collections.shuffle(local_questions);
    if (local_questions.size()>=questionsToBeShown)
        setQuestions(local_questions.subList(0, questionsToBeShown));
    getRequest().getSession().setAttribute("questionsForUser", getQuestions());
}

对于有类似问题的人:当您在List上执行subList时,会返回不实现Serializable接口的RandomAccessList。因此解决方案是将所有内容添加到一个序列化列表(如ArrayList)中。 - Omnipresent
3个回答

10

您可以使用可序列化的List实现并确保列表中的对象也是可序列化的,从而使对象可序列化。

是的——将只可序列化的对象放入会话中是个好习惯,因为这样可以在运行于具有多个节点的服务器上时使用您的应用程序。即使您目前不关心这一点,它未来可能会很有用。

Servlet容器应确保会话不会在用户之间交换。存储在会话中的可序列化对象允许容器将会话状态“分布”到集群中的多个节点,从而允许拥有该会话的用户由任何节点处理请求。


3
它要求它们可序列化,因为servlet规范指出如果web.xml中有“可分发”标记,则必须是可序列化的。规范假定servlet引擎将使用序列化在服务之间复制会话。 使其可序列化的唯一方法是...使用可序列化的List实现!您必须编写自己的自定义List类,因为我知道JDK中的所有实现都是可序列化的。或者列表中的对象不可序列化。 或者,如果您不关心会话是否在多个服务器之间复制,您可以删除“可分发”。

“questions”来自哪里?你使用ORM吗?许多ORM(如Hibernate)引入了自己的集合实现。您可能需要取消包装问题并将其包装到普通的ArrayList中。请还发布Question类的类定义。 - mhaller

0

如果JDK集合的元素可序列化,则它们全部都是可序列化的。我的猜测是List 元素 不可序列化,而不是List对象本身。简单来说,要使对象可序列化,必须:

  • 实现Serializable接口
  • 只有非静态、非瞬态字段也是可序列化的

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接