监听器实现在线用户监控

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/chengqiuming/article/details/100587055

一 监听器

RequestListener.java

package lee;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;

import java.sql.*;


@WebListener
public class RequestListener
    implements ServletRequestListener
{
    // 当用户请求到达、被初始化时触发该方法
    public void requestInitialized(ServletRequestEvent sre)
    {
        HttpServletRequest request = (HttpServletRequest)
            sre.getServletRequest();
        HttpSession session = request.getSession();
        // 获取session ID
        String sessionId = session.getId();
        // 获取访问的IP和正在访问的页面
        String ip = request.getRemoteAddr();
        String page = request.getRequestURI();
        String user = (String)session.getAttribute("user");
        // 未登录用户当游客处理
        user = (user == null) ? "游客" : user;
        try
        {
            DbDao dd = new DbDao("com.mysql.jdbc.Driver"
                , "jdbc:mysql://localhost:3306/online_inf"
                , "root" , "32147");
            ResultSet rs = dd.query("select * from online_inf where session_id=?"
                , true , sessionId);
            // 如果该用户对应的session ID存在,表明是旧的会话
            if (rs.next())
            {
                // 更新记录
                rs.updateString(4, page);
                rs.updateLong(5, System.currentTimeMillis());
                rs.updateRow();
                rs.close();
            }
            else
            {
                // 插入该用户的在线信息
                dd.insert("insert into online_inf values(? , ? , ? , ? , ?)",
                    sessionId , user , ip , page , System.currentTimeMillis());
            }
        }
        catch (Exception ex)
        {
            ex.printStackTrace();
        }
    }
    // 当用户请求结束、被销毁时触发该方法
    public void requestDestroyed(ServletRequestEvent sre)
    {
    }
}

OnlineListener.java

package lee;

import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;

import java.sql.*;
import java.awt.event.*;


@WebListener
public class OnlineListener
    implements ServletContextListener
{
    // 超过该时间(10分钟)没有访问本站即认为用户已经离线
    public final int MAX_MILLIS = 10 * 60 * 1000;
    // 应用启动时触发该方法
    public void contextInitialized(ServletContextEvent sce)
    {
        // 每5秒检查一次
        new javax.swing.Timer(1000 * 5 , new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                try
                {
                    DbDao dd = new DbDao("com.mysql.jdbc.Driver"
                        , "jdbc:mysql://localhost:3306/online_inf"
                        , "root" , "32147");
                    ResultSet rs = dd.query("select * from online_inf" , false);
                    StringBuffer beRemove = new StringBuffer("(");
                    while(rs.next())
                    {
                        // 如果距离上次访问时间超过了指定时间
                        if ((System.currentTimeMillis() - rs.getLong(5))
                            > MAX_MILLIS)
                        {
                            // 将需要被删除的session ID添加进来
                            beRemove.append("'");
                            beRemove.append(rs.getString(1));
                            beRemove.append("' , ");
                        }
                    }
                    // 有需要删除的记录
                    if (beRemove.length() > 3)
                    {
                        beRemove.setLength(beRemove.length() - 3);
                        beRemove.append(")");
                        // 删除所有“超过指定时间未重新请求的记录”
                        dd.modify("delete from online_inf where session_id in "
                            + beRemove.toString());
                    }
                    dd.closeConn();
                }
                catch (Exception ex)
                {
                    ex.printStackTrace();
                }
            }
        }).start();
    }
    public void contextDestroyed(ServletContextEvent sce)
    {
    }
}

二 DAO

package lee;

import java.sql.*;


public class DbDao
{
    private Connection conn;
    private String driver;
    private String url;
    private String username;
    private String pass;
    public DbDao()
    {
    }
    public DbDao(String driver , String url
        , String username , String pass)
    {
        this.driver = driver;
        this.url = url;
        this.username = username;
        this.pass = pass;
    }
    // 下面是各个成员变量的setter和getter方法
    public void setDriver(String driver) {
        this.driver = driver;
    }
    public void setUrl(String url) {
        this.url = url;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPass(String pass) {
        this.pass = pass;
    }
    public String getDriver() {
        return (this.driver);
    }
    public String getUrl() {
        return (this.url);
    }
    public String getUsername() {
        return (this.username);
    }
    public String getPass() {
        return (this.pass);
    }
    // 获取数据库连接
    public Connection getConnection() throws Exception
    {
        if (conn == null)
        {
            Class.forName(this.driver);
            conn = DriverManager.getConnection(url,username,
                this. pass);
        }
        return conn;
    }
    // 插入记录
    public boolean insert(String sql , Object... args)
        throws Exception
    {
        PreparedStatement pstmt = getConnection().prepareStatement(sql);
        for (int i = 0; i < args.length ; i++ )
        {
            pstmt.setObject( i + 1 , args[i]);
        }
        if (pstmt.executeUpdate() != 1)
        {
            return false;
        }
        pstmt.close();
        return true;
    }
    // 执行查询
    public ResultSet query(String sql , boolean updatable , Object... args )
        throws Exception
    {
        PreparedStatement pstmt = null;
        if (updatable)
        {
            // 创建可更新的PreparedStatement
            pstmt = getConnection().prepareStatement(sql
                , ResultSet.TYPE_SCROLL_INSENSITIVE
                , ResultSet.CONCUR_UPDATABLE);
        }
        else
        {
            pstmt = getConnection().prepareStatement(sql);
        }
        for (int i = 0; i < args.length ; i++ )
        {
            pstmt.setObject( i + 1 , args[i]);
        }
        return pstmt.executeQuery();
    }
    // 执行修改
    public void modify(String sql , Object... args)
        throws Exception
    {
        PreparedStatement pstmt = getConnection().prepareStatement(sql);
        for (int i = 0; i < args.length ; i++ )
        {
            pstmt.setObject(i + 1 , args[i]);
        }
        pstmt.executeUpdate();
        pstmt.close();
    }
    // 关闭数据库连接的方法
    public void closeConn()
        throws Exception
    {
        if (conn != null && !conn.isClosed())
        {
            conn.close();
        }
    }
}

三 测试页面online.jsp

<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ page import="java.sql.*,lee.*" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title> 用户在线信息 </title>
    <meta name="website" content="http://www.crazyit.org" />
</head>
<body>
在线用户:
<table width="640" border="1">
<%
DbDao dd = new DbDao("com.mysql.jdbc.Driver"
    , "jdbc:mysql://localhost:3306/online_inf"
    , "root"
    , "32147");
// 查询online_inf表(在线用户表)的全部记录
ResultSet rs = dd.query("select * from online_inf" , false);
while (rs.next())
{%>
<tr>
    <td><%=rs.getString(1)%>
    <td><%=rs.getString(2)%>
    <td><%=rs.getString(3)%>
    <td><%=rs.getString(4)%>
</tr>
<%}%>
</body>
</html>

四 数据库

drop database online_inf;

create database online_inf;

use online_inf;

create table online_inf
(
session_id varchar(255) primary key,
username varchar(255),
user_ip varchar(255),
access_res varchar(255),
last_access bigint
);

五 测试

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/100587055