最近做的《食盐行业信用管理与公共服务系统》项目,需要做一个网站文章页面的访问量功能。自己的解决方案,可能很简陋,但是解决了问题,而且我也给出了详细的过程。请大家多多支持,参与谈论。博客写这么长不容易啊。嘿嘿.

需求及规则如下:
1.同一个ip地址,两次刷新页面的时间,大于10秒,则认为是2次访问。
2.每天的凌晨0点到1点之间,执行插入或更新数据库操作。因此,网站页面展示的访问量,都是昨天的访问量。

思路及设计说明:
1.过滤器:过滤要计算访问量的某个页面或某些页面,当访问过滤页面时,组装访问量数据。
2.监听器:在项目启动时,启动定时器。
3.定时器:每隔一小时执行一次,如果时间处于0点-1点之间,则把访问量数据插入或更新进数据库,并清空ServletContext里面存放的访问量数据。
4.ServletContext:存放每天的访问量数据。因为ServletContext的生命周期是tomcat启动后,整个项目的生命周期。
5.本项目中采用的是springMVC,因此,附录的PagevisitRemark.java类添加了注解,请大家根据需要,自己写,不一定用我写的。

问题及解决:
1.开发中,遇到了在监听类中,无法调用到service层的方法,试了很多种办法都不行,可能是框架有问题,也可能是别的问题。
鉴于时间关系,没有解决,只能等以后再说了。反正是每天才执行一次插入或更新操作,最后就用了一个笨办法,直接用jdbc连接数据库,写sql语句了。
2.代码里面的MMap类,是我项目中经常用到的一个类。就是个封装数据的类。不用也没关系。

代码中所有的类都贴出来,用不到的自己删除。本文主要是提供一个解决思路和一个详细解决方案(虽然很笨)。
以后如果发现更好的办法。我会再次更新。欢迎积极留言讨论,请关注我的其它博客文章。
目录视图链接地址:http://blog.csdn.net/ludongshun2016?viewmode=contents

表结构

表约束

web.xml添加代码

<!-- 网站页面访问量,测试用,lds...begin -->
<filter><filter-name>PageVisitFilter</filter-name><filter-class>com.app.archive.web.filter.PageVisitFilter</filter-class>
</filter>
<filter-mapping><filter-name>PageVisitFilter</filter-name><url-pattern>/website/xiangxi_article.jsp</url-pattern>
</filter-mapping>
<listener><listener-class>com.app.archive.util.online.PageVisitListener</listener-class>
</listener>
<!-- 网站页面访问量,测试用,lds...end -->

监听器类(含定时器):PageVisitListener.java

package com.app.archive.util.online;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;import com.app.archive.model.salt.MMap;
import com.app.archive.model.salt.PagevisitRemark;/**
* <p>Title:PageVisitListener </p>
* <p>Description: 监听器,在程序启动时执行定时器,每隔一小时执行一次定时器,如果时间
* 在每天的0点-1点之间,则执行插入或更新数据库操作</p>
* @author 鲁东顺
* @date 2016-10-24 下午1:42:59*/
public class PageVisitListener implements ServletContextListener{private ServletContext context;@Overridepublic void contextDestroyed(ServletContextEvent arg0) {}@Overridepublic void contextInitialized(ServletContextEvent arg0) {this.context = arg0.getServletContext();timerRun();}/*** 定时器,每隔一小时执行一次,如果在0-1点之间,则执行插入数据库操作* lds*/public void timerRun() {//得到时间类Calendar date = Calendar.getInstance();//设置时间为 xx-xx-xx 00:00:00date.set(date.get(Calendar.YEAR), date.get(Calendar.MONTH), date.get(Calendar.DATE), 0, 0, 0);//一天的毫秒数long daySpan = 24 * 60 * 60 * 1000;//long daySpan = 60*1000*60;//1小时 //long daySpan = 30*1000;//30秒 ..测试时用//得到定时器实例Timer t = new Timer();//使用匿名内方式进行方法覆盖t.schedule(new TimerTask() {public void run() {//run中填写定时器主要执行的代码块Map<String, MMap> ipMap = (Map<String, MMap>) context.getAttribute("ipMap");Date d=new Date();int hour=d.getHours();//每天的凌晨0-1点之间执行if(hour>=0 && hour < 1){try {Thread.sleep(30000);//睡眠30秒,等待项目启动System.out.println("定时器执行..");if(null == ipMap){ipMap = new HashMap<String, MMap>();}insertOrUpdate(ipMap);ipMap = new HashMap<String, MMap>();context.setAttribute("ipMap", ipMap);System.out.println("定时器结束..");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}, date.getTime(), daySpan); //daySpan是一天的毫秒数,也是执行间隔};/*** 更新或插入操作* 鲁东顺*/public void insertOrUpdate(Map<String, MMap> ipMap){List<PagevisitRemark> sprList = new ArrayList<PagevisitRemark>();List<PagevisitRemark> uprList = new ArrayList<PagevisitRemark>();List<PagevisitRemark> prList = new ArrayList<PagevisitRemark>();if(null != ipMap && ipMap.size() > 0){prList = this.getAll();for (Object o : ipMap.keySet()) {MMap mmap = (MMap)ipMap.get(o);PagevisitRemark pr2 = new PagevisitRemark();if(null != prList && prList.size() > 0){for(int i = 0; i < prList.size(); i++){PagevisitRemark pr = prList.get(i);if(pr.getIp().equals(mmap.getObj()+"") && (pr.getArticleid()+"").equals(mmap.getObj1()+"")){pr2 = pr;pr2.setCount(Integer.parseInt(mmap.getObj2()+"")+pr2.getCount());break;}}}if(null == pr2.getId()){pr2.setArticleid(Integer.parseInt(mmap.getObj1()+""));pr2.setCount(Integer.parseInt(mmap.getObj2()+""));pr2.setIp(mmap.getObj()+"");sprList.add(pr2);}else{uprList.add(pr2);}}}if(null != uprList && uprList.size() > 0){this.updateAll(uprList);}if(null != sprList && sprList.size() > 0){this.insertAll(sprList);}}/*** 新增所有* 鲁东顺*/public static void insertAll(List<PagevisitRemark> prList) {Connection con = null;// 创建一个数据库连接PreparedStatement pre = null;// 创建预编译语句对象,一般都是用这个而不用StatementResultSet result = null;// 创建一个结果集对象try{Class.forName("oracle.jdbc.driver.OracleDriver");// 加载Oracle驱动程序System.out.println("开始尝试连接数据库!");String url = "jdbc:oracle:" + "thin:@211.88.1.111:1522:orcl";// 127.0.0.1是本机地址,XE是精简版Oracle的默认数据库名String user = "salt";// 用户名,系统默认的账户名String password = "salt";// 你安装时选设置的密码con = DriverManager.getConnection(url, user, password);// 获取连接System.out.println("连接成功!");for(int i = 0; i < prList.size(); i++){String sql = "insert into SALT_PAGEVISIT_REMARK (id,ip,articleid,count) values (SEQ_SALT_PAGEVISIT_REMARK.NEXTVAL,?,?,?)";// 预编译语句,“?”代表参数pre = con.prepareStatement(sql);// 实例化预编译语句pre.setString(1, prList.get(i).getIp());// 设置参数,前面的1表示参数的索引,而不是表中列名的索引pre.setInt(2, prList.get(i).getArticleid());// 设置参数,前面的1表示参数的索引,而不是表中列名的索引pre.setInt(3, prList.get(i).getCount());// 设置参数,前面的1表示参数的索引,而不是表中列名的索引result = pre.executeQuery();// 执行查询,注意括号中不需要再加参数}System.out.println("新增数据:"+prList.size()+"条。");}catch (Exception e){e.printStackTrace();}finally{try{// 逐一将上面的几个对象关闭,因为不关闭的话会影响性能、并且占用资源// 注意关闭的顺序,最后使用的最先关闭if (result != null)result.close();if (pre != null)pre.close();if (con != null)con.close();System.out.println("数据库连接已关闭!");}catch (Exception e){e.printStackTrace();}}}/*** 更新所有* lds*/public static void updateAll(List<PagevisitRemark> prList) {Connection con = null;// 创建一个数据库连接PreparedStatement pre = null;// 创建预编译语句对象,一般都是用这个而不用StatementResultSet result = null;// 创建一个结果集对象try{Class.forName("oracle.jdbc.driver.OracleDriver");// 加载Oracle驱动程序System.out.println("开始尝试连接数据库!");String url = "jdbc:oracle:" + "thin:@211.88.1.111:1522:orcl";// 127.0.0.1是本机地址,XE是精简版Oracle的默认数据库名String user = "salt";// 用户名,系统默认的账户名String password = "salt";// 你安装时选设置的密码con = DriverManager.getConnection(url, user, password);// 获取连接System.out.println("连接成功!");for(int i = 0; i < prList.size(); i++){String sql = "update SALT_PAGEVISIT_REMARK set count = ? where id = ?";// 预编译语句,“?”代表参数pre = con.prepareStatement(sql);// 实例化预编译语句pre.setInt(1, prList.get(i).getCount());// 设置参数,前面的1表示参数的索引,而不是表中列名的索引pre.setInt(2, prList.get(i).getId());// 设置参数,前面的1表示参数的索引,而不是表中列名的索引result = pre.executeQuery();// 执行查询,注意括号中不需要再加参数}    System.out.println("更新数据:"+prList.size()+"条。");}catch (Exception e){e.printStackTrace();}finally{try{// 逐一将上面的几个对象关闭,因为不关闭的话会影响性能、并且占用资源// 注意关闭的顺序,最后使用的最先关闭if (result != null)result.close();if (pre != null)pre.close();if (con != null)con.close();System.out.println("数据库连接已关闭!");}catch (Exception e){e.printStackTrace();}}}/*** 查询所有* lds*/public static List<PagevisitRemark> getAll() {Connection con = null;// 创建一个数据库连接PreparedStatement pre = null;// 创建预编译语句对象,一般都是用这个而不用StatementResultSet result = null;// 创建一个结果集对象List<PagevisitRemark> list = new ArrayList<PagevisitRemark>();try{Class.forName("oracle.jdbc.driver.OracleDriver");// 加载Oracle驱动程序System.out.println("开始尝试连接数据库!");String url = "jdbc:oracle:" + "thin:@211.88.1.111:1522:orcl";// 127.0.0.1是本机地址,XE是精简版Oracle的默认数据库名String user = "salt";// 用户名,系统默认的账户名String password = "salt";// 你安装时选设置的密码con = DriverManager.getConnection(url, user, password);// 获取连接System.out.println("连接成功!");String sql = "select id,ip,articleid,count from SALT_PAGEVISIT_REMARK";// 预编译语句,“?”代表参数pre = con.prepareStatement(sql);// 实例化预编译语句result = pre.executeQuery();// 执行查询,注意括号中不需要再加参数while(result.next()){// 当结果集不为空时PagevisitRemark pr = new PagevisitRemark();pr.setId(Integer.parseInt(result.getString("id")));//idpr.setIp(result.getString("ip"));//ippr.setArticleid(Integer.parseInt(result.getString("articleid")));//articleidpr.setCount(Integer.parseInt(result.getString("count")));//数量list.add(pr);}System.out.println("查询出数据:"+list.size()+"条。");}catch (Exception e){e.printStackTrace();}finally{try{// 逐一将上面的几个对象关闭,因为不关闭的话会影响性能、并且占用资源// 注意关闭的顺序,最后使用的最先关闭if (result != null)result.close();if (pre != null)pre.close();if (con != null)con.close();System.out.println("数据库连接已关闭!");}catch (Exception e){e.printStackTrace();}}return list;}
}

过滤器类PageVisitFilter.java

package com.app.archive.web.filter;import java.io.IOException;
import java.util.HashMap;
import java.util.Map;import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;import com.app.archive.model.salt.MMap;/**
* <p>Title:PageVisitFilter </p>
* <p>Description: 过滤器,用于统计文章页面访问量</p>
* @author 鲁东顺
* @date 2016-10-24 下午1:42:59*/
public class PageVisitFilter implements Filter{private FilterConfig filterConfig;@Overridepublic void destroy() {}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {String ip = request.getRemoteAddr();HttpServletRequest request1 = (HttpServletRequest) request;String url = request1.getRequestURI();if(null != url && !"".equals(url) && url.contains("/")){int aa = url.lastIndexOf("/");url = url.substring(aa+1,url.length());}String articleid = request1.getParameter("id");ServletContext context = filterConfig.getServletContext();Map<String, MMap> ipMap = (Map<String, MMap>) context.getAttribute("ipMap");if(null == ipMap){ipMap = new HashMap<String, MMap>();}ipMap = getIpMap(ipMap,ip,articleid);context.setAttribute("ipMap", ipMap);chain.doFilter(request, response);}/*** 计数操作* 鲁东顺*/private Map<String, MMap> getIpMap(Map<String, MMap> ipMap,String ip, String articleid){String key = "";if(null != articleid && !"".equals(articleid)){key = ip+"_"+articleid;if(null != ipMap && ipMap.size() > 0 && ipMap.containsKey(key)){//ipMap中包含当前key(登录ip+文章id) MMap mmap = ipMap.get(key);long d1 = System.currentTimeMillis()/1000;long d2 = Long.parseLong(mmap.getObj3()+"");long d3=d1-d2;if(d3 > 10){//相隔时间大约10秒,才算有效  System.out.println("两次刷新间隔:"+d3+"秒。");mmap.setObj2(Integer.parseInt(mmap.getObj2()+"")+1);}mmap.setObj3(System.currentTimeMillis()/1000);//访问时间}else{//ipMap中不包含当前keyMMap mmap = new MMap();mmap.setObj(ip);//登录ipmmap.setObj1(articleid);//文章idmmap.setObj2(1);//访问次数mmap.setObj3(System.currentTimeMillis()/1000);//访问时间ipMap.put(ip+"_"+articleid, mmap);}return ipMap;}return new HashMap<String, MMap>();}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {this.filterConfig = filterConfig;}}
**附:统计类PagevisitRemark.java**

package com.app.archive.model.salt;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Lob;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import java.util.Date;

/**
* @author SinoCredit
* @since 2016-10-21 13:19:01
* @version 1.0
* Company 北京**管理有限公司
* Descripion 测试用数据库表
*/
@Entity
@Table(name=”SALT_PAGEVISIT_REMARK”)
public class PagevisitRemark{

    @Id
@SequenceGenerator(name = "SEQ_SALT_PAGEVISIT_REMARK", sequenceName = "SEQ_SALT_PAGEVISIT_REMARK", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_SALT_PAGEVISIT_REMARK") /**  */
@Column(name="ID")
private Integer id;/** 访问者ip */
@Column(name="IP")
private String ip;/** 访问次数 */
@Column(name="COUNT")
private Integer count;/** 访问文章的id */
@Column(name="ARTICLEID")
private Integer articleid;/*** @return */
public Integer getId() {return this.id;
}
/*** @param _id */
public void setId(Integer _id) {this.id = _id;
}/*** @return 访问者ip*/
public String getIp() {return this.ip;
}
/*** @param _ip 访问者ip*/
public void setIp(String _ip) {this.ip = _ip;
}/*** @return 访问次数*/
public Integer getCount() {return this.count;
}
/*** @param _count 访问次数*/
public void setCount(Integer _count) {this.count = _count;
}/*** @return 访问文章的id*/
public Integer getArticleid() {return this.articleid;
}
/*** @param _articleid 访问文章的id*/
public void setArticleid(Integer _articleid) {this.articleid = _articleid;
}
}

附:MMap.java类(这个类只是我项目中常用的一个类,这里的功能不用非用这个类)

package com.app.archive.model.salt;import java.util.List;public class MMap {private String key;private Object obj;private Object obj1;private Object obj2;private Object obj3;private Object obj4;private Object obj5;private Object obj6;private Object obj7;private Object obj8;private Object obj9;private Object obj10;private List   list;public MMap() {super();}public MMap(String key, Object obj, Object obj1, Object obj2, Object obj3) {super();this.key = key;this.obj = obj;this.obj1 = obj1;this.obj2 = obj2;this.obj3 = obj3;}public MMap(String key, Object obj, Object obj1, Object obj2, Object obj3,Object obj4) {super();this.key = key;this.obj = obj;this.obj1 = obj1;this.obj2 = obj2;this.obj3 = obj3;this.obj4 = obj4;}public MMap(String key, Object obj, Object obj1, Object obj2, Object obj3, Object obj4, Object obj5,Object obj6) {super();this.key = key;this.obj = obj;this.obj1 = obj1;this.obj2 = obj2;this.obj3 = obj3;this.obj4 = obj4;this.obj5 = obj5;this.obj6 = obj6;}public String getKey() {return key;}public void setKey(String key) {this.key = key;}public Object getObj() {return obj;}public void setObj(Object obj) {this.obj = obj;}public Object getObj1() {return obj1;}public void setObj1(Object obj1) {this.obj1 = obj1;}public Object getObj2() {return obj2;}public void setObj2(Object obj2) {this.obj2 = obj2;}public Object getObj3() {return obj3;}public void setObj3(Object obj3) {this.obj3 = obj3;}public List getList() {return list;}public void setList(List list) {this.list = list;}public Object getObj4() {return obj4;}public void setObj4(Object obj4) {this.obj4 = obj4;}public Object getObj5() {return obj5;}public void setObj5(Object obj5) {this.obj5 = obj5;}public Object getObj6() {return obj6;}public void setObj6(Object obj6) {this.obj6 = obj6;}public Object getObj7() {return obj7;}public void setObj7(Object obj7) {this.obj7 = obj7;}public Object getObj8() {return obj8;}public void setObj8(Object obj8) {this.obj8 = obj8;}public Object getObj9() {return obj9;}public void setObj9(Object obj9) {this.obj9 = obj9;}public Object getObj10() {return obj10;}public void setObj10(Object obj10) {this.obj10 = obj10;}}

统计网站页面的访问量相关推荐

  1. 统计网站的用户访问量的实现

    1.项目需求:一个IP一天内访问算是一次访问,统计该网站的用户访问量. 2.实现思想:服务器启动的时候把数据库中的访问量进行缓存,用户访问的时候进行访问量的刷新,把访问信息存到集合中进行缓存,达到一定 ...

  2. js实现精确统计网站访问量的代码分享

    JS 精确统计网站访问量. 代码如下: /** * vlstat 浏览器统计脚本 */ var statIdName = "vlstatId"; var xmlHttp; /** ...

  3. linux网站ip访问量查询,如何统计网站每天PV和IP访问量排行

    近几天,官网登陆注册页面总是会有人进行账号密码试探,为了观察网站每天一些访问量情况,提早发现问题,特意统计了网站的页面及IP访问量,并将前10名,通过web页面展示出来. 1.分析页面和IP访问量排行 ...

  4. Servlet中统计网站访问量

    统计网站访问量 访问量 放入到servletContext里,,setAttribute("count"); 其他servlet获取该变量,然后进行自增 再重新放入到 servle ...

  5. java web统计网站访问次数,实现一个统计网站访问量的效能

    实现一个统计网站访问量的功能 大神们              用JS,jquery,ajax怎么实现一个统计网站访问量的功能 谢谢 ------解决方案-------------------- 这里 ...

  6. 如何统计网站各页面一天内的 PV 和 UV?

    大数据开发最常统计的需求可能就是 PV.UV.PV 全拼 PageView,即页面访问量,用户每次对网站的访问均被记录,按照访问量进行累计,假如用户对同一页面访问了 5 次,那该页面的 PV 就应该加 ...

  7. PHP+MySQL实现精确统计网站访问量(IP个数)

    基于WordPress的网站有很多统计功能.但是只能统计文章阅读数.不能统计访客人数.以下代码可以实现获取来访用户的IP地址,一个IP对应一次访问.即使刷新也不会增加访问量.这个非常精确. 1.创建一 ...

  8. 如何快速统计网站所有页面的文本字数

    文章目录 前言 一.WinHTTrack Website Copier是什么? 二.WinHTTrack Website Copier使用步骤 三.什么是Python? 四.Python实现的功能 前 ...

  9. 使用 Redis 统计网站 UV 的方法

    文章目录 前言 思路 HyperLogLog 使用 Redis 命令操作 使用 Java 代码操作 HyperLogLog 实现原理及特点 使用 Java 实现 HyperLogLog 小结 前言 网 ...

  10. JavaSpark | RDD实战:统计网站 pv 和 uv

    文章目录 1.pv 和 uv 1.1 什么是 PV 值? 1.2 什么是 UV 值? 2. 代码实战 JavaSpark | 算子 JavaSpark | RDD实战:WordCount JavaSp ...

最新文章

  1. Tomcat手动配置简述【查询留存】
  2. 怎样在Python中执行cmd
  3. ORA-00257: archiver error. Connect internal only, until freed 错误的处理方法
  4. bad cpu type in executable_【简讯】Intel将每5年重新开发一次CPU架构;华为EMUI 11曝光…...
  5. js中获取事件对象的方法小结
  6. 这个瑞士的项目没法在今年三月申请,因为我需要护照并且这个项目在人文社科学员下面,886
  7. 报告显示Q2 Android平板电脑全球市场份额达67%
  8. java包含关系图_Java——Spring框架完整依赖关系图!再复习了解加工一下吧?
  9. Entity Framework 4.1 : 贪婪加载和延迟加载
  10. 一切事物皆对象_基础篇
  11. zypper 删除mysql_如何在 Linux 上安装/卸载一个文件中列出的软件包?
  12. iOS 14惊现iPhone 12 Pro设计图细节:大失所望!
  13. SAP ASE 多个严重漏洞的详情披露
  14. 1062. 最简分数(20)-PAT乙级真题
  15. python循环遍历文件夹_如何用Python实现目录遍历
  16. 关于虚拟主机软件配置的问题
  17. ceb怎么转换成word_如何将ceb文件转成word_ceb文件转成word的详细步骤-系统城
  18. 卡巴斯基企业版本杀毒软件防火墙,支持windows服务器系统安装
  19. 服务器共享文档只读不可复制,局域网共享文件只读不存、共享文件只读不能复制设置法...
  20. 所以者何,须菩提。过去心不可得,现在心不可得,未来心不可得。

热门文章

  1. uniapp 复制 粘贴功能
  2. maven项目关系依赖
  3. 计算机桌面文件为何不能剪贴,复制粘贴,详细教您电脑复制粘贴不能用了怎么解决...
  4. MySQL 8.0版本连接报错:Could not create connection to database server.
  5. 学习s3c2440的随笔笔记
  6. 针对s3c2440芯片制作交叉编译工具链
  7. 【Java项目-飞翔的小鸟】附源码
  8. [NOIP 2009] 细胞分裂
  9. 宏碁 Acer AS4738ZG-P622G32Mncc 驱动
  10. CSS CSS3 pdf 电子书大全 百度云