在jsp中重置会话而不失效

Posted

技术标签:

【中文标题】在jsp中重置会话而不失效【英文标题】:Reset session in jsp without invalidating 【发布时间】:2016-05-11 10:33:12 【问题描述】:

我想在 JSP 页面中重置会话而不使其无效。 这样做的原因是,用户可能已经使用会话打开了一个页面,并且将其无效会抛出一个NullPointerException。由于已经捕获了新会话,因此我不想添加额外的流行语。目标是清除所有属性。

我正在寻找类似的东西:

session = new HttpSession(); //this does obviously not work

另一种选择是(?)

while(session.getAttributeNames().hasMoreElements())
    session.removeAttribute(session.getAttributeNames().nextElement());
    //cleans session?

但我不确定,这是否会删除一些必要的会话属性,例如登录数据。

有什么好的方法吗?

编辑:最好的解决方案是,每次打开某个页面时,您都会为该窗口/标签创建一个新会话,直到您关闭标签或在此标签中重新访问该页面。这个问题是在尝试解决this problem.时出现的

【问题讨论】:

但是,杀死所有值不会有风险访问不再可用的项目吗?您能否解释一下在哪些情况下您需要“清理”会话而不是更新会话? @Jan 在会话中我保存了一些用于控制保存的大量数据,因此我想完全刷新会话。但在其他一些选项卡中,我可能有一个其他控件运行的打开页面,我不喜欢用 NullPointer 崩溃。所以一个新的会话也可以,但如果我使用无效,它只是将另一个选项卡中的会话设置为null,这有点孬。不再可用的问题已经被捕获,因此我不想添加另一个短语。 好的。在多个会话属性下拥有所有这些数据可能很困难 - 您可能最终会得到您建议的循环。但是如何使用 one 会话密钥并为该密钥存储 Map<String,Object> 呢?这样你就可以((Map)session.getAttribute("myKey")).clear(); 这将是一种方式,但对我来说似乎有点开销,因为那时我需要在每个会话属性中添加地图(并且现在更改很多代码)。我只是希望,有一种方法或方式可以直接在会话中执行此操作(如问题中的第一行),以便在没有新请求的情况下应用新的会话实例或清理会话。 所以你想在一个页面中重置会话中的所有数据,但在另一个页面中仍然存在? 【参考方案1】:

HttpSession API 显然不提供这样的功能。

使用 Java5 迭代器习语,上面的循环可能会写得更好:

for (final String an : session.getAttributeNames()) 
    session.removeAttribute(an);

但这需要Enumeration to be iterable。

我想知道的是:您想清除 所有 会话数据,但仍保留该会话,以便其他似乎正在使用该会话的控件运行不会崩溃。这真的有效吗?第二次控制运行将找不到任何会话数据,因为您已完全清除会话。

我相信其中之一是正确的:

    您的会话清理会删除第二次控制运行所需的数据 最好使会话无效并启用控制运行来处理无效的会话。

HttpSession 文档明确指出,任何使用会话的实体都必须能够处理会话丢失或从不存在的事实,因此无论如何都应该实施第 2 点。

在可扩展性的意义上(如果会话中有来自其他进程的数据会发生什么?您的循环也会清除它们)我建议不要清除整个会话,而是跟踪您的控件放置的会话值- 仅运行并清除那些显式值。

【讨论】:

有趣的事实是我首先使用 for/in 语句尝试了它,但是由于枚举本身是不可迭代的(他们应该在 Java 8 中添加它),这种方式中的代码更少,而且更多可读。您的第一点是正确的,我的程序可以处理这种损失。到第二点:无效化对清除所有属性有什么好处?困扰我的不是属性的丢失,而是会话为空的事实。有没有办法至少将它设置为一个新实例?关于最后一句话:这是我现在真正考虑的事情(作为会话中添加的列表)。 再想一想:使会话无效没有任何好处,尤其是在更复杂的项目中,如果您不能确定还有谁在会话中存储了数据(但这适用于清除,也)。我只在某一时刻使用 invalidate:当用户注销并且我想确保没有任何经过身份验证的内容被留下时。除此之外,一般清理可能会丢弃某些模块可能仍需要的数据。 (但是我不知道你的项目——也许这根本不是问题。)【参考方案2】:

是的,有一个很好的方法可以做到这一点。创建一个包装HttpSession 对象的类并实现Map 接口。在实现中,您可以在不使会话失效的情况下操作会话属性。类似于 Struts2 框架中 SessionMap 的实现代码。您可以在此处阅读 SessionMap 的文档页面。

Map 接口的简单实现,用于处理 HTTP 会话属性。 entrySet() 方法枚举所有 会话属性并创建一个Set 的条目。请注意,这将发生 lazily - 仅在请求条目集时。

SessionMap 的类似实现可以在 JSF 中找到。您可以在文档页面找到here。

public class SessionMap extends
    java.util.AbstractMap<java.lang.String,V>

另见: javax.faces.context.ExternalContext#getSessionMap()

如果您使用这些框架中的任何一个,您可以使用或覆盖clear() 方法来获得您想要的。

【讨论】:

但是我仍然会遇到问题,我可能会删除身份验证对象。包装器将更容易处理清洁,因为它将更改保存在一个地方(为此+1,将实现类似的东西),但正确清洁的问题仍然存在。现在这两个实现也只是做我已经想到的相同的事情,运行所有属性并删除它们。如果有办法知道“系统”会话属性,那将有助于在清理时避免它们。 我已经在我的回答中回答了this。 这应该可行,我会尝试实现它。谢谢你的回答! (当我完成实施或时间用完时,您将获得赏金,无论是第一个:-))【参考方案3】:

你可以像我们在会话中设置值一样使用这个技巧

session.setAttribute( "name", "value");

不用重置整个会话对象,只需为会话参数设置一些空值,使其为空,session 对象不会抛出 NullPointerException。

例如

session.setAttribute( "name", "");

【讨论】:

您的意思是session.setAttribute("name", null); 您的代码会将属性设置为空字符串。将属性设置为null 几乎可以得到相同的输出,当您尝试获取它时,就像删除它一样。我现在能想到的唯一区别是,它仍然会保存为空属性(例如,您通过session.getAttributeNames() 获取它)。

以上是关于在jsp中重置会话而不失效的主要内容,如果未能解决你的问题,请参考以下文章

Django 会话变量重置

重置会话超时而不在 ASP.Net 中进行回发

Shiro 在 2 分钟后重置会话

在 CVS 中移动文件而不重置修订号

百度小程序重置了AppSecret,页面就失效了,要在那个里面怎么修改呢?

jsp中表单重置