会话未正确失效,抛出 "Session is invalid"
Session not invalidated properly, throwing "Session is invalid"
我有一个使用 Wildfly 10 作为服务器的 JSF 2.2 应用程序。
用户已登录并添加到在线用户列表中:
HttpSession session = request.getSession();
funcionario.setSessao(session);
funcionario.setIp(request.getRemoteAddr());
session.setAttribute("usuarioLogado", funcionario);
我从在线用户列表中删除注销的用户。
public class ActiveUserListener implements HttpSessionAttributeListene {
@Inject
Fixo fixo;
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
if (event.getValue() instanceof Funcionario) {
fixo.getLogins().add((Funcionario) event.getValue());
}
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
if (event.getValue() instanceof Funcionario) {
if (event.getValue() instanceof Funcionario) {
fixo.getLogins().remove((Funcionario) event.getValue());
}
}
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
if (event.getValue() instanceof Funcionario) {
fixo.getLogins().add((Funcionario) event.getValue());
}
} }
public class SessionCounter implements HttpSessionListener {
@Inject
Fixo fixo;
public void sessionDestroyed(HttpSessionEvent se) {
if (se.getSession().getAttribute("usuarioLogado") != null) {
Funcionario f = fixo.getLogins().stream().filter(o -> o.getSessaoId().equals(se.getSession().getId()))
.findAny().get();
fixo.getLogins().remove(f);
}
}
@Override
public void sessionCreated(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}}´
当我尝试打印一些 user/session 详细信息时:
public void usuConsole() {
System.out.println("nº " + fixo.getLogins().size());
for (Funcionario f : fixo.getLogins()) {
System.out.println(f.getMatricula());
if (f.getSessao() != null) {
System.out.println(f.getSessao().getId());
System.out.println(f.getSessao().getCreationTime());
System.out.println(f.getSessao().getLastAccessedTime());
}
}
}
打印一些行并在某个点:
Session is invalid R5EB6hKAzanm50PSRYqxcv361UMD6nGjZWxJVc5P
如果登录的用户少是可以的,但是登录退出的用户多了就会出现这个错误
选项 1:
尝试对 Fixo class 中的登录集合使用 java.util.concurrent.CopyOnWriteArrayList 实现。
选项 2
手动同步登录集合:
a) 使集合最终化(使用对象进行同步时的良好做法。
b) 在事件侦听器方法中同步登录集合的插入和移除:
synchronized(fixo.getLogins()){
fixo.getLogins().remove((Funcionario) event.getValue());
}
synchronized(fixo.getLogins()){
fixo.getLogins().add((Funcionario) event.getValue());
}
c) 同步每个循环:
synchronized(fixo.getLogins()){
for (Funcionario f : fixo.getLogins()) {
System.out.println(f.getMatricula());
if (f.getSessao() != null) {
System.out.println(f.getSessao().getId());
System.out.println(f.getSessao().getCreationTime());
System.out.println(f.getSessao().getLastAccessedTime());
}
}
}
现在,在任何这些同步块中,任何对登录集合的 public 方法调用都将被阻止,直到应用程序离开该块。
这意味着虽然 for each 循环是 运行,但事件侦听器方法中对集合的任何修改都将保留,直到循环结束。
根据listener spec,session只有在sessionDestroyed方法处理完成后才会失效。
至少理论上是这样,尝试一下,看看效果如何。
我有一个使用 Wildfly 10 作为服务器的 JSF 2.2 应用程序。
用户已登录并添加到在线用户列表中:
HttpSession session = request.getSession();
funcionario.setSessao(session);
funcionario.setIp(request.getRemoteAddr());
session.setAttribute("usuarioLogado", funcionario);
我从在线用户列表中删除注销的用户。
public class ActiveUserListener implements HttpSessionAttributeListene {
@Inject
Fixo fixo;
@Override
public void attributeAdded(HttpSessionBindingEvent event) {
if (event.getValue() instanceof Funcionario) {
fixo.getLogins().add((Funcionario) event.getValue());
}
}
@Override
public void attributeRemoved(HttpSessionBindingEvent event) {
if (event.getValue() instanceof Funcionario) {
if (event.getValue() instanceof Funcionario) {
fixo.getLogins().remove((Funcionario) event.getValue());
}
}
}
@Override
public void attributeReplaced(HttpSessionBindingEvent event) {
if (event.getValue() instanceof Funcionario) {
fixo.getLogins().add((Funcionario) event.getValue());
}
} }
public class SessionCounter implements HttpSessionListener {
@Inject
Fixo fixo;
public void sessionDestroyed(HttpSessionEvent se) {
if (se.getSession().getAttribute("usuarioLogado") != null) {
Funcionario f = fixo.getLogins().stream().filter(o -> o.getSessaoId().equals(se.getSession().getId()))
.findAny().get();
fixo.getLogins().remove(f);
}
}
@Override
public void sessionCreated(HttpSessionEvent arg0) {
// TODO Auto-generated method stub
}}´
当我尝试打印一些 user/session 详细信息时:
public void usuConsole() {
System.out.println("nº " + fixo.getLogins().size());
for (Funcionario f : fixo.getLogins()) {
System.out.println(f.getMatricula());
if (f.getSessao() != null) {
System.out.println(f.getSessao().getId());
System.out.println(f.getSessao().getCreationTime());
System.out.println(f.getSessao().getLastAccessedTime());
}
}
}
打印一些行并在某个点:
Session is invalid R5EB6hKAzanm50PSRYqxcv361UMD6nGjZWxJVc5P
如果登录的用户少是可以的,但是登录退出的用户多了就会出现这个错误
选项 1:
尝试对 Fixo class 中的登录集合使用 java.util.concurrent.CopyOnWriteArrayList 实现。
选项 2
手动同步登录集合:
a) 使集合最终化(使用对象进行同步时的良好做法。
b) 在事件侦听器方法中同步登录集合的插入和移除:
synchronized(fixo.getLogins()){
fixo.getLogins().remove((Funcionario) event.getValue());
}
synchronized(fixo.getLogins()){
fixo.getLogins().add((Funcionario) event.getValue());
}
c) 同步每个循环:
synchronized(fixo.getLogins()){
for (Funcionario f : fixo.getLogins()) {
System.out.println(f.getMatricula());
if (f.getSessao() != null) {
System.out.println(f.getSessao().getId());
System.out.println(f.getSessao().getCreationTime());
System.out.println(f.getSessao().getLastAccessedTime());
}
}
}
现在,在任何这些同步块中,任何对登录集合的 public 方法调用都将被阻止,直到应用程序离开该块。 这意味着虽然 for each 循环是 运行,但事件侦听器方法中对集合的任何修改都将保留,直到循环结束。 根据listener spec,session只有在sessionDestroyed方法处理完成后才会失效。
至少理论上是这样,尝试一下,看看效果如何。