今天用listener做了一个网站计数器,功能是记录历史访问量和当前在线人数。代码如下:web.xml:<context-param>
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <context-param>
  <description>web counter</description>
  <param-name>counterPath</param-name>
  <param-value>connter.txt</param-value>
 </context-param>
 <listener>
  <description>implements ServletContextListener</description>
  <listener-class>com.cs.listener.CounterListener</listener-class>
 </listener>
 <listener>
  <description>implements HttpSessionListener</description>
  <listener-class>com.cs.listener.SessionListener</listener-class>
 </listener>
 <welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>
 <login-config>
  <auth-method>BASIC</auth-method>
 </login-config>
</web-app>CounterListener.javapackage com.cs.listener;import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;public class CounterListener implements ServletContextListener { public void contextInitialized(ServletContextEvent evt) {

FileOperator fo = new FileOperator();

String file = evt.getServletContext().getInitParameter("counterPath"); String fileLocation = evt.getServletContext().getRealPath(file); long currentRecord = fo.readFile(fileLocation); evt.getServletContext().setAttribute("web_counter", currentRecord);
} public void contextDestroyed(ServletContextEvent evt) {

long currentRecord = (Long)evt.getServletContext().getAttribute("web_counter");

FileOperator fo = new FileOperator();

String file = evt.getServletContext().getInitParameter("counterPath"); String fileLocation = evt.getServletContext().getRealPath(file);

fo.writeFile(fileLocation, currentRecord);
}
}SessionListener.javapackage com.cs.listener;import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;public class SessionListener implements HttpSessionListener { public void sessionCreated(HttpSessionEvent evt) {

long currentRecord = ((Long)evt.getSession().getServletContext().getAttribute("web_counter")); currentRecord++; evt.getSession().getServletContext().setAttribute("web_counter",currentRecord); long online = 1;

Long hisOnline = (Long)evt.getSession().getServletContext().getAttribute("online_counter"); if(hisOnline != null){
online += hisOnline;
}

evt.getSession().getServletContext().setAttribute("online_counter",online);

System.out.println("online :" + online);
} public void sessionDestroyed(HttpSessionEvent evt) { long online = (Long)evt.getSession().getServletContext().getAttribute("online_counter"); online--; evt.getSession().getServletContext().setAttribute("online_counter",online);

System.out.println("online :" + online);
}}
JSP中的代码:<body>
  
  历史访问量:<%= (Long)application.getAttribute("web_counter")%>
  
  <br>
  
  当前在线人数:<%=application.getAttribute("online_counter") %>
  </body>问题是:页面访问的时候数据都能读的出来,但是浏览器窗口关闭的时候sessionDestroyed并没有执行(应该说是没有马上执行)。反正sessionDestroyed中的打印语句没打印出出东西,在另外一个浏览器(opera和maxthon两个浏览器)中刷新也没有反应。不知过了多久我刷新了一下,当前在线人数竟然变成负数了。挺晕的,我想 当我关掉浏览器窗口的时候session是不是就该销毁。服务器端是怎么知道客户端浏览器关闭的? 负数是怎么出现的,我想无论怎么都不会是负数啊。另外一个问题在web.xml中是设置session生命周期单位是什么??  时间是怎么算的,比方说设置30分钟,是从创建时起30分钟还是从客户端没有活动起30分钟。都什么情况下session会被销毁??

解决方案 »

  1.   

    客户端没有活动30分钟
    关掉浏览器session还是存在的 在服务器端  服务器端不知道浏览器关闭
      

  2.   

    如果监听器没有之行的话
    根据我有次的经验把它的配置放到web.xml的最前面试试 
    我曾经出现过一次这样的问题
      

  3.   


    关掉浏览器之后服务器端不知道客户端已经关掉了  那服务器端要等待session过期是么  也就是说我们关掉浏览器三十分钟之后   如果我们设置的session时间是30分钟的话 
      

  4.   

    package com.qiter.listener;import java.util.Date;import javax.servlet.ServletContext;
    import javax.servlet.http.HttpSession;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    /**
     * 
     * 统计用户访问总数
     *
     */
    public class CountUserListener implements HttpSessionListener{

    private Date begin;

    public void sessionCreated(HttpSessionEvent event) {
    HttpSession session = event.getSession();
    ServletContext application = event.getSession().getServletContext();
    int count = 10000;
    if(application.getAttribute("count")!=null){
    count = Integer.parseInt(
    application.getAttribute("count").toString()
    );
    }
    count++;
    application.setAttribute("count", new Integer(count));


    Date begin = new Date();
    session.setAttribute("begin", begin);
    } public void sessionDestroyed(HttpSessionEvent event){
    HttpSession session = event.getSession();
    Date begin = (Date)session.getAttribute("begin");

    Date end = new Date();//现在销毁的时间
    long time = end.getTime()-begin.getTime();//在线时间单位为毫秒
    int s = (int)time/1000;  //秒
    System.out.println("此用户在线时间为"+s+"秒");
    }}
    你说的题目我做过,呵呵!!!
      

  5.   


    那浪费了好多内存  我们访问结束之后30分钟服务器才销毁 session  又没什么好的办法 当浏览器关掉是  服务器就可以感知到
      

  6.   


    老大 我是想知道我的sessionDestroyed方法是什么时间调用的 ,好像是也调用了 但是是关掉浏览器之后的一段时间之后   session的默认时间是30分钟吧    我没设置  但关掉浏览器之后不到30分钟在线认识就减少了   我是自己做实验的    用两个浏览器    也就是说服务器还是知道了浏览器关掉了  而不是session过期了
      

  7.   


    监听器执行了  就是sessionDestroyed方法不是在浏览器关掉之后就执行的    不知道过了多久  就执行了