序列化之前从会话中删除属性

时间:2014-11-25 11:34:08

标签: java session java-ee

我在用户会话中保存了一些引用,这些引用链接到不可序列化的对象。 我希望在应用程序关闭之前,在会话序列化之前从会话中删除这些属性。

有没有办法这样做? 我已经尝试使用监听器来监听app destroy,但是当时会话已经失效。

2 个答案:

答案 0 :(得分:5)

您可以创建第二个类,将第一个非序列化包装到对象引用中,并将其标记为transient

public class Wrapper implements Serializable
{
    public transient YourClass obj;
}

transient变量在序列化后不会被序列化,并且在null对象的反序列化后将被分配到Wrapper

答案 1 :(得分:0)

您可以使用HttpSessionActivationListener并在sessionWillPassivate方法中实现清理逻辑。

/**
 * Clean-up listener for removing non-serializable session attributes from session.
 * <p>
 * To activate simply register this class as servlet listener in {@code web.xml}:
 * <pre>
 * &lt;listener>
 *     &lt;listener-class>com.example.SessionCleanupListener&lt;/listener-class>
 * &lt;/listener>
 * </pre>
 */
public class SessionCleanupListener implements HttpSessionListener, HttpSessionActivationListener, Serializable {

    private static final long serialVersionUID = 1L;

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // Register self as session attribute to get `passivation` events
        se.getSession().setAttribute(this.getClass().getName(), this);
    }

    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        HttpSession session = se.getSession();
        Enumeration<String> names = session.getAttributeNames();
        while (names.hasMoreElements()) {
            String name = names.nextElement();
            if (!(session.getAttribute(name) instanceof Serializable)) {
                session.removeAttribute(name);
            }
        }
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        // no-op
    }

    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        // no-op
    }

}