版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
一 监听器
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
);
五 测试