1.概述
网站计数器对于网站管理者来说是一个非常值得关注的部分,它记录了网站被访问的次数,客观地反映了网站受欢迎的程度。如果网站的点击率很高,访问者也会认为网站值得关注,因而耐心驻足,进而增加网站的访问量,提高网站的知名度。
本实例中主要应用Servlet中的过滤器技术统计网站的访问量,并且将客户端的IP地址、登录时间和网站的访问次数存储到数据库中;然后在网站的页面中以图形的形式输出网站的访问量,同时还输出网站的最后登录IP和登录时间。
2.技术要点
别致图形计数器设计主要应用Servlet过滤器完成网站访问量数据的统计。应用Servlet过滤器必须实现Filter接口。下面对Filter接口进行详细讲解。
Filter接口
Filter接口存放于javax.servlet包中,是过滤器必须实现的接口。主要包含以下三个方法:
init()方法,在doFilter()方法前被调用,负责设置FilterConfig对象。语法如下:
public void init(FilterConfig filterConfig) throws ServletException
filterConfig:为过滤器提供初始化参数和访问ServletContext对象。
doFilter()方法,过滤器的主要方法,当客户端请求目标资源时,容器就会调用与这个目标资源相关联的过滤器的doFilter()方法。实现对请求和响应进行处理,执行过滤器的特殊功能。
doFilter()方法的语法如下:
public synchronized void doFilter(ServletRequest request, ServletResponse response, FilterChain Chain) throws ServletException, IOException
当过滤器的特殊功能完成后,则调用Chain.doFilter(request, response)将请求传给下一个过滤器(或者目标资源),也可以直接向客户端返回响应信息,或者应用RequestDispatcher的forward()和include()方法,以及HttpServletResponse的sendRedirect()方法将请求转向其他资源。
destroy()方法,结束过滤器的生命周期,释放过滤器使用的资源。语法如下:
public void destroy()
3.具体实现
(1)创建db_database01数据库,在数据库中创建tb_counts数据表,用于存储客户的登录时间、客户端的IP地址和网站的访问次数。
(2)编写连接和操作数据库的公共类UserDao。包括加载数据库驱动的方法、连接数据库的方法、查询数据的方法、更新数据库的方法和关闭数据库的方法。其中通过selectStatic()方法实现对数据库的查询操作,关键代码如下:
public ResultSet selectStatic(String sql) throws SQLException { ResultSet rs=null; //定义ResultSet接口的返回值 if (con == null) { //判断如果数据库没有连接 Connection(); //则执行该方法,连接数据库 } try { stmt = con.createStatement(); //创建返回Statement实例 rs = stmt.executeQuery(sql); //执行静态sql语句 } catch (SQLException e) { e.printStackTrace(); } return rs; }
通过executeUpdate()方法实现更新数据库中数据的操作,关键代码如下:
public boolean executeUpdate(String sql) { if (con == null) { //判断如果数据库没有连接 Connection(); //则执行该方法,连接数据库 } try { stmt = con.createStatement(); //创建返回Statement实例 int iCount = stmt.executeUpdate(sql); //执行静态sql语句 System.out.println("操作成功,所影响的记录数为" + String.valueOf(iCount)); } catch (SQLException e) { System.out.println(e.getMessage()); return false; } closeConnection(); //关闭数据库的操作 return true; }
(3)编写Stat_flux类。创建read_Flux()方法,读取数据库中的数据,并且将读取的数据写入到List集合;创建write_Flux()方法执行更新数据库中数据的操作;创建Stat_count()方法,实现将数据库中的访问量由数字到图形的转换。
read_Flux()方法的关键代码如下:
public List<String> read_Flux() { List<String> list = new ArrayList<String>(); //通过ArrayList类实例化List集合 try { String sqls = "select * from tb_counts "; //定义sql查询语句 ResultSet rss = conn.selectStatic(sqls); //调用数据库操作类中的方法执行查询操作 rss.next(); //获取查询结果 String counts = rss.getString("counts"); //获取统计次数 String last_ip = rss.getString("last_ip"); //获取最后的访问IP String last_date = rss.getString("last_date"); //获取最后的访问时间 String str_pic = Stat_count(counts); //执行统计数字转换成图形类中的方法,并获取到返回结果 conn.closeConnection(); //执行关闭数据库的操作 list.add(last_ip); //将ip地址添加到List中 list.add(last_date); //将时间添加到List中 list.add(str_pic); //将图形数据添加到List中 } catch (SQLException e) { e.printStackTrace(); } return list; }
Stat_count()方法的关键代码如下:
public String Stat_count(String counts){ String zeno=""; int length=counts.length(); //获取字符串的长度 int i=0; while(i<10-length){ //根据字符串的总长度,计算出补位值0的个数 zeno+="<img src='images\0.jpg'/>"; //循环输出图形中代表0的图形 i++; } String count=""; //定义变量,用于输出指定字符代表的图形 int ii=0; while(ii<length){ //根据字符串的长度进行循环输出 count+="<img src='images\"+counts.charAt(ii)+".jpg'/>"; //输出字符串中指定字符代表的图形 ii++; } String backstr=zeno+count; //定义字符串变量,合并输出结果 return backstr; //返回输出结果 }
(4)编写Servlet过滤器类Filter_flux,实现通过过滤器来统计网站的流量。首先创建init()方法,然后创建doFilter()方法,实现输出和更新网站访问量数据的功能,为了更准确的统计出网站的访问量,还通过自定义变量flux和session变量实现了防止页面刷新的功能;最后创建destroy()方法。Filter_flux类的关键代码如下:
public class Filter_flux extends HttpServlet implements Filter { private static int flux = 0; Stat_Flux stat_flux = new Stat_Flux(); public void init(FilterConfig filterConfig) throws ServletException { } public synchronized void doFilter(ServletRequest request, ServletResponse response, FilterChain Chain) throws ServletException, IOException { HttpSession session = ((HttpServletRequest) request).getSession(); //初始化session变量 if (flux == session.getAttribute("flux")) { //判断当flux的值等于session的值时,直接读取记录 List<String> list = stat_flux.read_Flux(); request.setAttribute("count", list.get(2)); //将获取到数据写入到request请求中 request.setAttribute("last_ip", list.get(0)); //将获取到数据写入到request请求中 request.setAttribute("last_date", list.get(1)); //将获取到数据写入到request请求中 } else { this.flux++; //flux值增加 session.setAttribute("flux", flux); //将flux的值写入到session中 String ip = request.getRemoteAddr(); //获取客户端的IP DateTime DateTime = new DateTime(); //实例化获取日期时间类 String datetime = DateTime.DateTime(); //调用日期时间类中方法获取当前时间 stat_flux.write_Flux(ip, datetime); List<String> list = stat_flux.read_Flux(); request.setAttribute("count", list.get(2)); //将获取到数据写入到request请求中 request.setAttribute("last_ip", list.get(0)); //将获取到数据写入到request请求中 request.setAttribute("last_date", list.get(1)); //将获取到数据写入到request请求中 } Chain.doFilter(request, response); } public void destroy() { } }
最后,在web.xml文件中配置Filter_flux类,首先使用<filter-name>与<filter-class>标签配置filter的名称与所在包的类名,然后再通过<filter-mapping>标签配置filter的映射路径,关键代码如下:
<filter> <!-- filter的名称 --> <filter-name>Filter_flux</filter-name> <!-- filter t的所在包的类名称 --> <filter-class>com.pkh.Filter_flux</filter-class> </filter> <filter-mapping> <!-- filter的映射名称 --> <filter-name>Filter_flux</filter-name> <!-- filter 的映射路径 --> <url-pattern>/*</url-pattern> <!-- filter 的映射使用的类型 --> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping>
(5)创建index.jsp页,应用getAttribute方法获取网站最后登录的IP地址、登录时间和网站的访问量。