gpt4 book ai didi

JSF 事件 session 计数器。如何?

转载 作者:行者123 更新时间:2023-12-04 22:07:45 25 4
gpt4 key购买 nike

晚上好,

在测试 JSF 2.0 Web 应用程序中,我试图获取事件 session 的数量,但 HttpSessionListener 的 sessionDestroyed 方法存在问题。
确实,当一个用户登录时,事件 session 的数量增加了1,但是当一个用户注销时,这个数字保持不变(不会发生减增量),更糟糕的是,当同一个用户再次登录时(即使他使 session 无效),相同的数字也会增加。
用不同的话来说:

1- 我登录后,事件 session 数加 1。
2- I 注销( session 未验证)
3-我再次登录, session 数加1。显示= 2。
4-我重复操作, session 数不断增加,而只有一个用户登录。

所以我认为方法 sessionDestroyed 没有正确调用,或者可能在 session 超时之后有效调用,这是 WEB.XML 中的一个参数(我的是 60 分钟)。
这很奇怪,因为这是一个 session 监听器,我的类(class)没有任何问题。

有人有线索吗?

package mybeans;

import entities.Users;
import java.io.*;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import jsf.util.JsfUtil;

/**
* Session Listener.
* @author TOTO
*/
@ManagedBean
public class SessionEar implements HttpSessionListener {

public String ctext;
File file = new File("sessionlog.csv");
BufferedWriter output = null;
public static int activesessions = 0;
public static long creationTime = 0;
public static int remTime = 0;
String separator = ",";
String headtext = "Session Creation Time" + separator + "Session Destruction Time" + separator + "User";

/**
*
* @return Remnant session time
*/
public static int getRemTime() {
return remTime;
}

/**
*
* @return Session creation time
*/
public static long getCreationTime() {
return creationTime;
}

/**
*
* @return System time
*/
private String getTime() {
return new Date(System.currentTimeMillis()).toString();
}

/**
*
* @return active sessions number
*/
public static int getActivesessions() {
return activesessions;
}

@Override
public void sessionCreated(HttpSessionEvent hse) {
// Insert value of remnant session time
remTime = hse.getSession().getMaxInactiveInterval();

// Insert value of Session creation time (in seconds)
creationTime = new Date(hse.getSession().getCreationTime()).getTime() / 1000;
if (hse.getSession().isNew()) {
activesessions++;
} // Increment the session number
System.out.println("Session Created at: " + getTime());
// We write into a file information about the session created
ctext = String.valueOf(new Date(hse.getSession().getCreationTime()) + separator);
String userstring = FacesContext.getCurrentInstance().getExternalContext().getRemoteUser();

// If the file does not exist, create it
try {
if (!file.exists()) {
file.createNewFile();

output = new BufferedWriter(new FileWriter(file.getName(), true));
// output.newLine();
output.write(headtext);
output.flush();
output.close();
}

output = new BufferedWriter(new FileWriter(file.getName(), true));
//output.newLine();
output.write(ctext + userstring);
output.flush();
output.close();
} catch (IOException ex) {
Logger.getLogger(SessionEar.class.getName()).log(Level.SEVERE, null, ex);
JsfUtil.addErrorMessage(ex, "Cannot append session Info to File");
}

System.out.println("Session File has been written to sessionlog.txt");

}

@Override
public void sessionDestroyed(HttpSessionEvent se) {
// Desincrement the active sessions number
activesessions--;


// Appen Infos about session destruction into CSV FILE
String stext = "\n" + new Date(se.getSession().getCreationTime()) + separator;

try {
if (!file.exists()) {
file.createNewFile();
output = new BufferedWriter(new FileWriter(file.getName(), true));
// output.newLine();
output.write(headtext);
output.flush();
output.close();
}
output = new BufferedWriter(new FileWriter(file.getName(), true));
// output.newLine();
output.write(stext);
output.flush();
output.close();
} catch (IOException ex) {
Logger.getLogger(SessionEar.class.getName()).log(Level.SEVERE, null, ex);
JsfUtil.addErrorMessage(ex, "Cannot append session Info to File");
}

}
} // END OF CLASS

我正在以这种方式检索事件 session 数:
<h:outputText id="sessionsfacet" value="#{UserBean.activeSessionsNumber}"/> 

来自另一个 managedBean:
public String getActiveSessionsNumber() {
return String.valueOf(SessionEar.getActivesessions());
}

我的注销方法如下:
 public String logout() {
HttpSession lsession = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(false);
if (lsession != null) {
lsession.invalidate();
}
JsfUtil.addSuccessMessage("You are now logged out.");
return "Logout";
}
// end of logout

最佳答案

我不确定。这似乎适用于单个访问者。但是有些事情在您的 HttpSessionListener 中看起来肯定不正确。

@ManagedBean
public class SessionEar implements HttpSessionListener {

为什么是 @ManagedBean ?没意义,删了。在 Java EE 6 中,您将改用 @WebListener
    BufferedWriter output = null;

这应该 绝对 不是实例变量。它不是线程安全的。将其声明为methodlocal。对于每个 HttpSessionListener 实现,在应用程序的整个生命周期中只有一个 一个 实例。当同时创建/销毁 session 时,您的 output 会在忙碌时被另一个 session 覆盖,并且您的文件会损坏。
    public static long creationTime = 0;
public static int remTime = 0;

这些也不应该是实例变量。每一个新的 session 创建都会覆盖它,它会反射(reflect)到所有其他用户的演示中。 IE。它不是线程安全的。如果出于某种原因需要将它们放在那里,请摆脱它们并在 EL 中使用 #{session.creationTime}#{session.maxInactiveInterval}。或者直接从 HTTP 请求中的 HttpSession 实例获取它。
    if (hse.getSession().isNew()) {

这是 sessionCreated() 方法中总是 true。这没有任何意义。去掉它。
        JsfUtil.addErrorMessage(ex, "Cannot append session Info to File");

我不知道该方法究竟在做什么,但我只想警告说, 不能保证 在 session 即将创建或销毁时线程中存在 FacesContext。它可能发生在非 JSF 请求中。或者可能根本没有 HTTP 请求的方法。所以你冒着 NPE 的风险,因为 FacesContext 就是 null

尽管如此,我创建了以下测试片段,它对我来说很好用。 @SessionScoped bean 隐式地创建 session 。命令按钮使 session 无效。所有方法都按预期调用。您在同一浏览器选项卡中还按下按钮多少次,计数始终为 1。

<h:form>
<h:commandButton value="logout" action="#{bean.logout}" />
<h:outputText value="#{bean.sessionCount}" />
</h:form>


@ManagedBean
@SessionScoped
public class Bean implements Serializable {

public void logout() {
System.out.println("logout action invoked");
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
}

public int getSessionCount() {
System.out.println("session count getter invoked");
return SessionCounter.getCount();
}

}


@WebListener
public class SessionCounter implements HttpSessionListener {

private static int count;

@Override
public void sessionCreated(HttpSessionEvent event) {
System.out.println("session created: " + event.getSession().getId());
count++;
}

@Override
public void sessionDestroyed(HttpSessionEvent event) {
System.out.println("session destroyed: " + event.getSession().getId());
count--;
}

public static int getCount() {
return count;
}

}

(注意 Java EE 5,您需要以通常的方式将其注册为 <listener> 中的 web.xml)

<listener>
<listener-class>com.example.SessionCounter</listener-class>
</listener>

如果上面的例子适合你,那么你的问题可能出在其他地方。也许您根本没有在 <listener> 中将其注册为 web.xml 并且您只是在每次登录方法中手动创建监听器的新实例。无论如何,现在您至少有一个最小的启动示例可以进一步构建。

关于JSF 事件 session 计数器。如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6311643/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com