在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中重置会话而不失效的主要内容,如果未能解决你的问题,请参考以下文章