1、实现思路:通过检查HttpServletRequest监控在线用户的状况;
=>OnlineListener.java
=>DbDao.java
a、采用ServletRequestListener监听器负责监听每次用户请求:当用户请求到达时,系统将用户请求的sessionID、用户名、用户IP、正在访问的资源、访问时间记录下来(新请求增加,旧请求更新记录;通过会话ID查询数据表是否存在来判断);
b、启动后台线程,她每隔一段时间检查上面的每条在线记录,如果某条在线记录的访问时间与当前时间相差超过指定值,将这条在线记录删除;这线程应该随着应用的启动而启动,可考虑ServletContextListener来启动、销毁;
2、实现
=>RequestListener.java
<span style="font-size:18px;"> package lee;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.sql.*;
/**
* RequestListener_class
* description:在线用户_记录用户信息(每次用户请求到达时,如果是新的用户会话,将相关信息插入数据表;如果是老的用户会话,则更新数据表中已有的在线记录);
* date:17:02 2014-10-30;
* @author cyb_23
* @version 1.0
*/
@WebListener
public class RequestListener implements ServletRequestListener
{
//当用户请求到达、被初始化时触发该方法
public void requestInitialized(ServletRequestEvent sre)
{
HttpServletRequest request = (HttpServletRequest)
sre.getServletRequest();
HttpSession session = request.getSession();
//------记录信息------
String sessionId = session.getId(); // 获取session ID;
String ip = request.getRemoteAddr(); // 获取访问的IP;
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)
{
}
}
</span>
=>OnlineListener.java
<span style="font-size:18px;"> package lee;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;
import java.sql.*;
import java.awt.event.*;
/**
* OnlineListener_class
* description:ServletContextListener实例,负责启动后台线程,这线程将会定期检查在线记录,删除那些长时间没有重新请求过的记录;
* date:17:10 2014-10-30;
* @author cyb_23
* @version 1.0
*/
@WebListener
public class OnlineListener
implements ServletContextListener
{
//超过该时间(10分钟)没有访问本站即认为用户已经离线
public final int MAX_MILLIS = 10 * 60 * 1000;
//应用启动时触发该方法
public void contextInitialized(ServletContextEvent sce)
{
//每5秒检查一次(使用计算器Timer)
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)
{
}
}</span>
=>DbDao.java
<span style="font-size:18px;"> package lee;
import java.sql.*;
/**
* DbDao_class
* description:数据库操作类;
* date:17:21 2014-10-30;
* @author cyb_23
* @version 1.0
*/
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,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();
}
}
}</span>