网站里的数据统计可以说是最基本的功能,关于访问人数、今日访问量等数据可以很好地反应出网站的活跃程度。今天徐伟轩博客就为大家整理了网站统计在线人数等信息的功能,希望会对大家有所帮助。
PHP统计在线人数,今日访问量,总访问量
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 <?php
header('Content-type: text/html; charset=utf-8');
$online_log = "count.dat"; //保存人数的文件,
$timeout = 30;//30秒内没动作者,认为掉线
$entries = file($online_log);
$temp = array();
for ($i=0;$i<count($entries);$i++) {
$entry = explode(",",trim($entries[$i]));
if (($entry[0] != $_SERVER["REMOTE_ADDR"]) && ($entry[1] > time())) {
array_push($temp,$entry[0].",".$entry[1]."\n"); //取出其他浏览者的信息,并去掉超时者,保存进$temp
}
}
array_push($temp,$_SERVER["REMOTE_ADDR"].",".(time() + ($timeout))."\n"); //更新浏览者的时间
$users_online = count($temp); //计算在线人数
$entries = implode("",$temp);
//写入文件
$fp = fopen($online_log,"w");
flock($fp,LOCK_EX); //flock() 不能在NFS以及其他的一些网络文件系统中正常工作
fputs($fp,$entries);
flock($fp,LOCK_UN);
fclose($fp);
echo "当前在线".$users_online."人";?>
专业版统计在线人数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 #内网地址段改为自己的
/ip firewall address-list add address=192.168.1.0/24 disabled=no list=lan
/ip firewall mangle add action=add-src-to-address-list address-list=Online address-list-timeout=1m chain=prerouting comment=tongji disabled=no src-address-list=lan
/system scheduler
add comment=tongji disabled=no interval=3m name="\CD\B3\BC\C6" on-event="#\D7\EE\B4\F3\D1\AD\BB\B7\B4\CE\CA\FD\r\
\n:global rmaxlimit 5000\r\
\n:global r 0\r\
\n:global rn\r\
\n:global rs\r\
\n:global ravg\r\
\n:global rmax\r\
\n:if ([:len \$ravg] = 0) do={\r\
\n:set ravg 0\r\
\n:global rn 0\r\
\n:global rs 0\r\
\n:global rmax 0}\r\
\n:if (\$rs = \$rmaxlimit) do={\r\
\n:global rn \$ravg\r\
\n:global rs 1}\r\
\n:foreach b in=[/ip firewall add find list=\"Online\"] do={:set r (\$r+1)}\r\
\n:if (\$rmax < \$r) do={:set rmax \$r}\r\
\n:set rs (\$rs+1)\r\
\n:set rn (\$rn+\$r)\r\
\n:global ravg (\$rn / \$rs)\r\
\n:log warning (\"\B5\B1\C7\B0\D4\DA\CF\DF\BF\CD\BB\A7\BB\FA\" . \$r . \"\CC\A8,\C6\BD\BE\F9\D4\DA\CF\DF\BF\CD\BB\A7\BB\FA\"\
\_. \$ravg . \",\D7\EE\B8\DF\D4\DA\CF\DF\C0\FA\CA\B7\" . \$rmax . \"\CC\A8,\B5\B1\C7\B0\CD\B3\BC\C6\B4\CE\CA\FD\" . \$rs . \
\"\A1\A3\")" policy=reboot,read,write,policy,test,password,sniff,sensitive start-date=jan/01/1970 start-time=00:00:00
统计在线人数以及在线人信息
-
web.xml
<?xml version=”1.0″ encoding=”UTF-8″?>
<web-app version=”2.5″ xmlns=”http://java.sun.com/xml/ns/javaee”1
2
3
4
5
6
7
8
9
10
11
12
13xmlns: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">
<!-- 统计在线人数-->
<listener>
<listener-class>com.wri.itmag.OnlineCounterListener</listener-class>
</listener>
<!-- session超时定义,单位为分钟 update by ChangPeng 2014-04-24 session超时时间设置为30分钟 -->
<session-config>
<session-timeout>30</session-timeout>
</session-config>
2.OnlineCounterListener.java
对Session对象实现监听,首先必须继承HttpSessionListener类,该程序的基本原理就是当浏览者访问页面的时候必定会产生一个session对象;当关闭该页面的时候必然会删除该session对象。所以每当产生一个新的session对象就让在线人数加1,当删除一个session对象就让在线人数减1。还要继承一个HttpSessionAttributeListener,来实现对其属性的监听。分别实现attributeAdded方法,attributeReplace方法以及attributeRemove方法。
sessionCreated//新建一个会话时候触发也可以说是客户端第一次和服务器交互时候触发
sessionDestroyed//销毁会话的时候 一般来说只有某个按钮触发进行销毁 或者配置定时销毁 ( 很多文献中提到说浏览器关闭时候会销毁 但是楼主通过各种现行主流浏览器测试效果不尽如人意)
HttpSessionAttributeListener有3个接口需要实现
attributeAdded//在session中添加对象时触发此操作 笼统的说就是调用setAttribute这个方法时候会触发的
attributeRemoved//修改、删除session中添加对象时触发此操作 笼统的说就是调用 removeAttribute这个方法时候会触发的
attributeReplaced//在Session属性被重新设置时
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 package com.wri.itmag;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import com.wri.itmag.vo.personalInfo.UserVO;
public class OnlineCounterListener implements HttpSessionListener,
HttpSessionAttributeListener {
public static int onLineCount; // 用于统计在线人数
/**
* 查询在线人名称,用于前台页面对于在线人名称的展示
*/
public static Set<String> onLinePersonList = new HashSet<String>();//用于
/**
* 用于查询在线人详细信息
*/
private Map<String, Object> sessionMap = new HashMap<String, Object>();
public void sessionCreated(HttpSessionEvent hse) {
// HttpSession session = hse.getSession();
// sessionMap.put(session.getId(), session);
// onLineCount = sessionMap.size();
}
public void sessionDestroyed(HttpSessionEvent hse) {
// onLineCount = sessionMap.size();
}
public void attributeAdded(HttpSessionBindingEvent hsbe) {
String name = hsbe.getName();
if ("userVO".equals(name)) {
UserVO userVO = (UserVO) hsbe.getValue();
sessionMap.put(userVO.getId() + "", userVO);
onLineCount = sessionMap.size();
onLinePersonList.add(userVO.getUser_name());
}
}
public void attributeRemoved(HttpSessionBindingEvent hsbe) {
String name = hsbe.getName();
if ("userVO".equals(name)) {
UserVO userVO = (UserVO) hsbe.getValue();
sessionMap.remove(userVO.getId() + "");
onLineCount = sessionMap.size();
//System.out.println(userVO.getId() + "" + userVO.getUser_name());
onLinePersonList.remove(userVO.getUser_name());
}
}
public void attributeReplaced(HttpSessionBindingEvent hsbe) {
String name = hsbe.getName();
if ("userVO".equals(name)) {
UserVO userVO = (UserVO) hsbe.getValue();
sessionMap.remove(userVO.getId() + "");
onLineCount = sessionMap.size();
onLineCount++;
onLinePersonList.remove(userVO.getUser_name());
}
}
}
3.LoginAction.java
实现用户登录,登出,以及登录成功页面跳转的功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130 package com.wri.itmag.action.login;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.sf.json.JSONObject;
import com.wri.itmag.OnlineCounterListener;
import com.wri.itmag.action.BaseAction;
import com.wri.itmag.common.LoginUserLog;
import com.wri.itmag.service.personalInfo.UserInfoService;
import com.wri.itmag.service.syscfg.DataDictManageService;
import com.wri.itmag.vo.personalInfo.UserVO;
public class LoginAction extends BaseAction {
private UserInfoService userInfoService;
private String userAccount;
private String password;
/**
* 登录操作
*/
public String login() throws Exception {
UserVO userVO = null;
HttpSession session = this.getSession();
try {
userVO = userInfoService.checkUser(userAccount, password);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
try {
if (userVO != null) {
HttpServletRequest request = this.getRequest();
// 登陆信息
LoginUserLog loginUserLog = new LoginUserLog(userVO.getId(),
request.getRemoteAddr());
// 放入session
session.setAttribute("loginUserLog", loginUserLog);
session.setAttribute("userVO", userVO);
session.setAttribute("userJson", JSONObject.fromObject(userVO));
this.outJsonString("{success:true,message:'登陆成功'}");
} else {
this.outJsonString("{success:false,message:'请检查用户名和密码....'}");
}
} catch (Exception ex) {
ex.printStackTrace();
throw ex;
}
return null;
}
/**
* 用户退出
*/
public String logout() throws Exception {
HttpSession session = this.getSession();
// 从session中获取用户信息
UserVO userVO = (UserVO) session.getAttribute("userVO");
LoginUserLog loginUserLog = (LoginUserLog) session
.getAttribute("loginUserLog");
if (loginUserLog != null) {
if (loginUserLog.isExist(loginUserLog.getUid())) {
session.setAttribute("loginUserLog", null);
session.setAttribute("userVO", null);
session.invalidate();
}
}
// session.setAttribute("userVO", null);
// session.invalidate();
this.outJsonString("{success:true}");
return null;
}
/**
* 登录成功操作
*/
public String loginSucc() throws ServletException, IOException {
// 传递角色
HttpSession session = this.getSession();
UserVO userVO = (UserVO) session.getAttribute("userVO");
this.outJsonString("{success:true,userVO:'"
+ JSONObject.fromObject(userVO) + "',isMyDemand:'" + isMyDemand
+ "'}");
return null;
}
/**
* 登陆成功后跳转到主界面
*/
public String jump() throws ServletException, IOException {
HttpSession session = this.getSession();
HttpServletRequest request = this.getRequest();
HttpServletResponse response = this.getResponse();
if (session.isNew()) {
response.sendRedirect("login.html");
} else {
UserVO userVO = (UserVO) session.getAttribute("userVO");
if (userVO != null) {
request.setAttribute("userVO", userVO);
request.setAttribute("logTime", new SimpleDateFormat(
"yyyy-MM-dd").format(new Date()));
request.setAttribute("onlineCount",
OnlineCounterListener.onLineCount);
request.setAttribute("onLinePersonList",
OnlineCounterListener.onLinePersonList);
request.getRequestDispatcher("/WEB-INF/main.jsp").forward(
request, response);
} else {
response.sendRedirect("login.html");
}
}
return null;
}
}
4.main.jsp 做页面展示 :在登陆完成后跳转到主页面就会显示在线人数,鼠标移至人数上时候,就会显示所有在线人信息,鼠标移出就自动隐藏。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 ...
<span title=""
style="font-size: 13px; font-family: 宋体; position: absolute; right: 5px; width: 80px;" onmouseover="showOnLinePersonList()" onmouseout="hideOnLinePersonList()"> 在线:${onlineCount}人
</span>
<span id="onlinePersonList" style="display:none;font-size: 13px; font-family: 宋体; position: absolute; top:10px ;right: 10px; width: 80px;">
<div id="firstDiv" align="center" style="backgroud-color:#8069ff ;border-style:solid;border-width:1px">所有在线人</div>
<div id="secondDiv" align="center">
<c:forEach items="${onLinePersonList}" var ="list">
<ol ><c:out value="${list}"/> </ol>
</c:forEach>
</div>
</span>
.....
<script>
function showOnLinePersonList(){
document.getElementById('onlinePersonList').style.display="block";
}
function hideOnLinePersonList(){
document.getElementById('onlinePersonList').style.display="none";
}
</script>
未解决的问题:以上的代码可以成功的实现在线人数的统计,但是对于在线展示在线人信息的时候,还有bug存在。出现的情况为:如果在同一个客户端,一个用户登录之后,没有做登出的操作(即session没有销毁),此时再以另一个用户登录,这个时候就相当于session中的name为“uservo”的attribute被替换了,也就调用了OnlineCounterListener类中的attributeReplace方法,代码如下:onLinePersonList先要remove掉之前的用户,加入新的用户,但是attributeRemoved(HttpSessionBindingEvent hsbe)中hsbe.getValue()拿到的是之前的值,没法拿到新的用户的值,所以不知道如何把新登录的这个用户加到set里面去,求解!!!
1
2
3
4
5
6
7 if ("userVO".equals(name)) {
UserVO userVO = (UserVO) hsbe.getValue();
sessionMap.remove(userVO.getId() + "");
onLineCount = sessionMap.size();
onLineCount++;
onLinePersonList.remove(userVO.getUser_name());
}
以上代码转载自互联网,好记性不如烂笔头,做开发就必须把很多细小知识点记录下来。
原文链接:https://letus.top/archives/163.html,转载请注明出处 来自[徐伟轩博客]。
评论0