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地址、登录时间和网站的访问量。