📄 visitorsoper.java
字号:
/* * 作者: 胡李青 * qq: 31703299 * Copyright (c) 2007 huliqing * 主页 http://www.tbuy.biz/ * 你可以免费使用该软件,未经许可请勿作用于任何商业目的,如有技术问题请与本人联系! */package biz.tbuy.common;import biz.tbuy.common.bean.BaseBean;import biz.tbuy.common.logs.Elog;import biz.tbuy.common.logs.Vlog;import biz.tbuy.message.MessageAction;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import javax.el.ELContext;import javax.el.ExpressionFactory;import javax.el.ValueExpression;import javax.faces.application.Application;import javax.faces.context.FacesContext;import javax.servlet.http.HttpSession;/** * @author huliqing * <p><b>qq:</b>31703299 * <p><b>E-mail:</b><a href="mailto:huliqing.cn@gmail.com">huliqing.cn@gmail.com</a> * <p><b>Homepage:</b><a href="http://www.tbuy.biz/">http://www.tbuy.biz/</a> */public class VisitorsOper extends BaseBean{ private Map<String,Visitor> _visitors; // 用户在线列表 private int _freeTime = 60 * 10;// 如果无动作超时时间(秒),则视为离线,默认60 * 10 private long _interval = 30; // 以一定的时间间隔让线程sleep,默认:30 private Thread _vListener; // 用户在线的监测线程 private int _totalOnline; // 总在线人数 private int _totalUser; // 在线用户数 private int _totalHidden; // 在线隐身人数 private int _totalGuest; // 在线访客 private Vlog _vlog; // 关于在线用户访问记录 public VisitorsOper() { _visitors = new HashMap<String, Visitor>(); } /** * 开始监测线程,该线程用于监测在线用户列表的状态,当用户在一定时间范围内无任何动作 * 时,将用户移除出在线列表 */ public void oper() { initVlog(); // 启动日志记录 _vListener = new Thread(new VisitorsListener()); _vListener.start(); } /*************************************************************************** * 关于在线用户处理, _visitors中包含了当前的所有在线用户(含隐身登录)及访客 * 可通过这样获取在线用户: * _visitors.get(用户id),获得当前在线用户, * _visitors.get(visitor.getVisitorKey()),获得当前访客用户,因为访客并未登录, * 无法得知用户id * 该方法用于获得当前所有用户的在线列表,包含隐身登录用户 * @return visitors; HashMap **************************************************************************/ public Map<String, Visitor> getVisitors() { return _visitors; } /** * 获取在线总用户数,包含访客,登录,隐身等 * @return totalOnline; */ public int getTotalOnline() { return _totalOnline; } /** * 获取在线登录用户数量,包含隐身登录者 * @return totalUser; */ public int getTotalUser() { return _totalUser; } /** * 获取在线隐身登录者的数量 * @return totalHidden */ public int getTotalHidden() { return _totalHidden; } /** * 获取在线访客数量,即未登录者 * @return totalGuest */ public int getTotalGuest() { return _totalGuest; } /** * 使用访问日志记录工具,记录一个新的访问者 * @param visitor */ /* public void logNewVisitor(Visitor visitor) { _vlog.log(visitor); } */ /** * 检查IP是否被允许访问 * @param ip */ private boolean checkAllow(String ip) { List<String> disallows = getComApplication().getDisallows(); if (disallows.contains(ip)) { return false; } return true; } /** 关于在线用户列表 ******************************************************** * 添加一个在线用户,该方法会自动判断用户是否已经在线或是否已经登录等, * 以考虑是否添加入_visitors列表 * @param visitor 要添加进在线列表的用户 */ public void checkVisitor(Visitor visitor) { // 检查IP是否已经被限制 if (!checkAllow(visitor.getIp())) { getFacesContext().responseComplete(); return; } if (visitor.isLogin()) { if (_visitors.get(visitor.getUser().getId()) == null) { addVisitor(visitor); } } else { if (_visitors.get(visitor.getVisitorKey()) == null) { addVisitor(visitor); } } } /** * 添加一个新visitor */ public void addVisitor(Visitor visitor) { if (visitor.isLogin()) { _visitors.put(visitor.getUser().getId(), visitor); _totalUser++; if (visitor.isHidden()) { _totalHidden++; } } else { // 未登录,则以"visitorKey"为KEY _visitors.put(visitor.getVisitorKey(), visitor); _totalGuest++; } _totalOnline++; _vlog.log(visitor); } /** * 减少一个在线用户,该方法主要用于从在线用户列表中清除掉一个用户, * 如:用户点击了“退出”后,需要将该用户从在线列表中清除出去,以更 * 新在线列表 * @param visitor 被移除出在线列表的visitor */ public void removeVisitor(Visitor visitor) { if (visitor.isLogin()) { Visitor pVisitor = _visitors.get(visitor.getUser().getId()); if (pVisitor != null) { _visitors.remove(visitor.getUser().getId()); _totalOnline--; _totalUser--; if (visitor.isHidden()) { _totalHidden--; } } } else { _visitors.remove(visitor.getVisitorKey()); _totalOnline--; _totalGuest--; } // 记录离开的用户 _vlog.logLeave(visitor); } /** * 同时从在线用户列表中删除多个用户,并使用日志访问工具记录离开的用户 * 该方法只负责删除在线列表中的用户,并不负责计算在线用户数。注意..... */ public void removeVisitors(List<Visitor> visitors) { _visitors.values().removeAll(visitors); _vlog.logLeave(visitors); } /** * 统一从这里登录一个用户,当用户已经通过验证的情况下。 * @param user 已经通过验证的用户 * @param hidden 是否以隐身方式登录 */ public void login(biz.tbuy.user.UserModel user, boolean hidden) { FacesContext fc = getFacesContext(); Application app = getApplication(); ELContext elc = getELContext(); ExpressionFactory ef = app.getExpressionFactory(); ValueExpression ve = ef.createValueExpression(elc, "#{" + Constants.VISITOR_KEY_SCOPE + Constants.VISITOR_KEY + "}", Visitor.class); Visitor visitor = null; try { visitor = (Visitor) ve.getValue(elc); } catch (Exception e) {} if (visitor != null) { // 如果原visitor不为null,则必须先从在线用户列表中清除原来的visitor, // 再重新设置visitor属性,成为新的visitor removeVisitor(visitor); visitor.setUser(user); visitor.setLogin(true); visitor.setHidden(hidden); } else { // 新建visitor时,不需要移除visitors列表 visitor = new Visitor(); visitor.setUser(user); visitor.setLogin(true); visitor.setHidden(hidden); ve.setValue(elc, visitor); } // 判断并设置该用户是否有新的短讯件 visitor.setNews(MessageAction.isNewMessages(user.getId())); // 判断,并确定是否需要将visitor加入在线列表 checkVisitor(visitor); } /** * 这里才是真正让用户退出系统的地方,并非Login类,因为用户的退出需要影响到在线列表 * 的实时更新,所以统一在这里退出 * @param visitor */ public void logout(Visitor visitor) { removeVisitor(visitor); HttpSession session = (HttpSession)getFacesContext(). getExternalContext().getSession(false); if (session != null) { session.invalidate(); } } /** * 重新计算在线用户信息 */ public void countOnline() { Set<String> keys = _visitors.keySet(); _totalUser = 0; _totalHidden = 0; _totalGuest = 0; for (String key : keys) { Visitor visitor = _visitors.get(key); if (visitor.isLogin()) { _totalUser++; if (visitor.isHidden()) { _totalHidden++; } } else { _totalGuest++; } } } /** * 显示在线列表_visitors的状态于控制台中 */ public void showVisitors() { if (!_visitors.isEmpty()) { Set<String> keys = _visitors.keySet(); System.out.println("--------visitors state"); for (String key : keys) { System.out.println(key + ":" + _visitors.get(key).getUser().getId()); } } else { System.out.println("no visitors"); } } /** * 显示在线用户数 */ private void showOnline() { System.out.println("totalOnline:" + _totalOnline); System.out.println("totalUser:" + _totalUser); System.out.println("totalHidden:" + _totalHidden); System.out.println("totalGuest:" + _totalGuest); } /** * 内部线程类,用于在线列表的监测,当用户在一定时间内无任何页面动作时,将视用户为 * 离线状态,并移除出在线列表。 */ private class VisitorsListener implements Runnable{ public VisitorsListener() {} @Override public void run() { while (true) { //System.out.println("vListener..."); if (!_visitors.isEmpty()) { Iterator<String> keys = _visitors.keySet().iterator(); // 将被移除的visitor List<Visitor> visitorsRe = new ArrayList<Visitor>(); while (keys.hasNext()) { String key = keys.next(); Visitor visitor = _visitors.get(key); long nowTime = System.currentTimeMillis(); long lastVisitTime = visitor.getLastVisitTime(); if ((nowTime - lastVisitTime) / 1000 > _freeTime) { visitorsRe.add(visitor); /** * 使用keys.remove可以独个、安全的删除在线用户列表中的 * 用户,而不会出现异常报错,但考虑到性能因素,还是使用 * 一并移除的方式,先将需要移除的用户加入visitorsRe, * 检查完后再一并移除. */ keys.remove(); // 超时离线,即移出在线列表 // _vlog.logLeave(visitor); // 计算在线用户信息 _totalOnline--; if (visitor.isLogin()) { _totalUser--; if (visitor.isHidden()) { _totalHidden--; } } else { _totalGuest--; } } } removeVisitors(visitorsRe); } //showOnline(); //showVisitors(); try { Thread.sleep(1000 * _interval); // 让线程停止一些时间 } catch (InterruptedException ie) { Elog.log("InterruptedException:VisitorsOper:VisitorsListener:" + ie.getMessage()); } } } }// end Thread /*************************************************************************** * 关于在线访问日志的记录,访方法用于起动Vlog类,_vlog用于登记新用户的访问,及记 * 录离开用户等,主要记录访问者的ip,开始访问时间,以及退出时间,如果用户使用id登 * 录,则同时记录id号 **************************************************************************/ private void initVlog() { _vlog = new Vlog(); } /** * 获取访问日志记录工具 * @return vlog */ public Vlog getVlog() { return _vlog; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -