如何实现图像访问计数器

系统 1522 0

统计和显示页面的访问次数是一个常见的 WEB 应用,因为在网页每次被访问时,页面的访问次数都要发生改变,所以这个功能必须通过服务器端的程序来实现。页面访问计数器在服务器端的基本执行过程为:首先从数据库或其他存储系统中取出页面原来的访问次数,然后将原来的访问次数加 1 后再作为当前访问次数送给浏览器显示,同时将当前访问次数存储回数据库或其他存储系统中,以便下次访问该页面时使用。但是,一些 WEB 站点只能输出静态页面内容,没有开放运行服务器端程序的功能。例如,一些提供免费网页空间的站点,在客户端访问任何类型的文件时,服务器都会原封不动地输出给浏览器去处理,显然无法直接在这些只支持静态内容的 WEB 站点上编写服务器端程序来实现页面访问次数的统计和显示功能。于是,一些具有执行服务器端程序功能的 WEB 站点推出了免费的页面访问计数器,只要在位于任何站点的一个静态 HTML 页面中增加一条该站点提供的 HTML 语句,该语句就能显示出该静态页面的访问次数,从而帮助静态 HTML 页面实现了访问次数的统计和显示功能。一个站点要想能统计另外一个站点上的某个 HTML 页面的访问次数,必须让任何一个浏览器在每次访问那个 HTML 页面都通知这个一下站点,这可以通过在静态 HTML 页面中增加两种特殊的标签来实现: <img> 标签和设置 src 属性的 <script> 标签。下面只分析使用 <img> 标签的应用情况,对于使用设置 src 属性的 <script> 标签的应用情况,则作为一道习题交给读者自己去完成。

要利用 <img> 标签为静态 HTML 页面实现访问次数的统计和显示功能,需要理解 <img> 标签的三个重要特性:

1 )一个包含有图像的网页文件中并没有包含真正的图像数据内容,而只是使用 <img> 标签指明了图像的 URL 地址,如下所示:

本网页已被浏览了 <img src= "count.gif ">

如果浏览器在解析网页文档 的过程中遇到了 <img> 标签 ,它根据 <img> 标签的 src 属性所指定的 URL 地址 去访问 WEB 服务器,从 WEB 服务器上获取图像数据后,再在 <img> 标签的位置处显示出来。

2 <img> 标签的 src 属性也可以指向当前页面所在 WEB 服务器之外的其他 WEB 服务器上的图像文件。

3 )浏览器并不关心 <img> 标签所需的图像数据在服务器端是如何产生,它只知道去访问 src 属性指定的 URL 资源,并把服务器返回的数据当作一个图像的内容来显示。服务器返回的图像数据可以直接从一个静态图像文件中读取,也可以通过 Servlet 程序在内存中动态创建。所以, <img> 标签的 src 属性指向的 URL 不一定非得是事先静态存在的静态图像文件,也可以是一个 Servlet 程序。

在静态 HTML 页面中使用 <img> 标签实现免费页面访问计数器的工作原理如图 5.17 所示, WEB 站点 A 上的静态页面 count.html 内有一条 <img> 标签语句, <img> 标签的 src 属性指向了 WEB 站点 B 上的一个名为 CountServlet Serlvet 程序,当浏览器显示从站点 A 上获得的 count.html 页面时,它将根据其中的 <img> 标签的 src 属性去访问 WEB 站点 B 上的 CountServlet 程序以获得要显示的图像数据, CountServlet 则创建出具有该页面的访问次数的图像回送给浏览器显示。

如何实现图像访问计数器

<shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f"><stroke joinstyle="miter"></stroke><formulas><f eqn="if lineDrawn pixelLineWidth 0"></f><f eqn="sum @0 1 0"></f><f eqn="sum 0 0 @1"></f><f eqn="prod @2 1 2"></f><f eqn="prod @3 21600 pixelWidth"></f><f eqn="prod @3 21600 pixelHeight"></f><f eqn="sum @0 0 1"></f><f eqn="prod @6 1 2"></f><f eqn="prod @7 21600 pixelWidth"></f><f eqn="sum @8 21600 0"></f><f eqn="prod @7 21600 pixelHeight"></f><f eqn="sum @10 21600 0"></f></formulas><path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"></path><lock v:ext="edit" aspectratio="t"></lock></shapetype><shape id="_x0000_i1025" style="WIDTH: 368.25pt; HEIGHT: 236.25pt" type="#_x0000_t75"><imagedata src="file:///C:%5CDOCUME~1%5Cgaocao%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image001.png" o:title='耠"耨"X'></imagedata></shape>

5.17

因为 WEB 站点 B 上并不存在客户端要访问的图像文件,而是由 Servlet 程序在内存中临时动态生成图像内容后传送到客户端的,所以,尽管静态页面内的 <img> 标签所指向的这个 Servlet 程序的 URL 地址是固定不变的,但是,它每次被访问时所返回的图像内容却是可以不断变化的。

要编写一个用 <img> 标签统计和显示静态 HTML 页面的访问次数的 Servlet 程序,需要考虑以下一些技术细节:

l Servlet 程序输出的图像格式为 jpeg ,所以,它应告诉浏览器其所输出的实体内容的 MIME 类型为 image/jpeg ,浏览器才会将它所接收到的数据当作一个图像进行处理。

l 因为图像是二进制数据,所以应该调用 HttpServletResponse.getOutputStream 方法返回的 ServletOutputStream 对象来向客户端写入图像数据,而不应使用 HttpServletResponse.getWriter 方法返回的 PrintWriter 对象。

l java.awt.image.BufferedImage 类用于在内存中创建一幅图像,具体的图像内容则可以通过调用其图形上下文对象( java.awt.Graphics )的各种绘图方法生成,这里仅仅需要绘制一串数字,调用 Graphics.drawString 方法即可。 BufferedImage 类创建的内存图像的初始背景颜色和绘图颜色都是黑色的,如果想改变背景颜色,还需要先设置相应的绘图颜色,然后调用 Graphics.fillRect 填充整个背景。

l 在内存图像中绘制访问次数时,必须限定显示的位数,如果访问次数超过七位,则用数字 9999999 显示,如果访问次数不足七位,则在前面补充相应个数的 0

l 每个引用该 Servlet 程序的静态页面的 URL 都对应一个各自的访问次数,每个 URL 及其访问次数需要使用数据库系统来进行存储,对于简单的实验,也可以采用一个属性文件来进行存储。程序首先使用 Referer 请求头获得当前引用页面的 URL ,然后去数据库或属性文件中检索该 URL 的访问次数,再将访问次数加 1 后保存进数据库或属性文件,并将访问次数绘制在内存图像中。如果属性文件中不存在该 URL 的信息,则说明该 URL 页面属于第一次统计访问。关于如何获得 Referer 请求头,请参看 6.4 节的讲解。

l JDK 中提供了一个 javax.imageio.ImageIO 类,它的 write 方法可以将 BufferedImage 对象中的图像编码成 jpeg 格式的图像数据后写入到一个 OutputStream 流对象中。因此,只需要调用 ImageIO.write 方法将 BufferedImage 对象中的图像编码成 jpeg 格式后写入到 ServletOutputStream 流对象中,就将整个图像数据输出给了客户端。

: 动手体验: 使用 <img> 标签实现静态 HTML 页面的访问次数统计和显示

1 )编写一个能统计静态 HTML 页面的访问次数和将访问次数以图像形式返回给客户端的 Servlet 程序,每个页面的 URL 及访问次数用一个属性文件进行存储,如例程 5-10 所示。

例程 5-10 CountServlet.java

<wrap side="left"><font face="Times New Roman" size="3"></font></wrap>


import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import java.awt.*;

import java.awt.image.*;

import javax.imageio.ImageIO;

import java.util.Properties;

public class CountServlet extends HttpServlet

{

public void doGet(HttpServletRequest request,

HttpServletResponse response) throws ServletException,IOException

{

response.setContentType("image/jpeg");

// 设置浏览器不要缓存此图片

response.setHeader("Pragma","No-cache");

response.setHeader("Cache-Control","no-cache");

response.setDateHeader("Expires", 0);

ServletOutputStream sos = response.getOutputStream();

BufferedImage image =

new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);

Graphics g = image.getGraphics();

/*g.setColor(Color.BLACK);

g.fillRect(0, 0, width, height);*/

g.setColor(Color.WHITE);

g.setFont(new Font(null,Font.ITALIC|Font.BOLD,18));

String value = getAccessCount(request);

int len = value.length();

// 最大访问次数不能超过 9999999

if(len > 7)

{

value = "9999999";

}

else

{

String tmp="";

for(int i=0;i<7-len;i++)

{

tmp = tmp +"0";

}

value = tmp + value;

}

g.drawString(value,0,18);

// 结束图像 的绘制 过程, 完成图像

g.dispose();

ImageIO.write(image, "JPEG", sos);

sos.close();

}

private String getAccessCount(HttpServletRequest request)

{

// 得到引用页面的 URL 地址,并以此作为访问次数的检索关键字

String pageKey = request.getHeader("referer");

if(pageKey == null)

{

return "0";

}

Properties settings = new Properties();

//count.txt 等内部文件最好是保存在 WEB-INF 目录中

String countFilePath = getServletContext().getRealPath("/count.txt");

try

{

// 下面的语句没有使用 close 方法关闭流,有缺陷!

settings.load(new FileInputStream(countFilePath));

}

catch(Exception e){}

String count = "0";

try

{

count = settings.getProperty(pageKey);

if(count == null)

{

count = "0";

}

int c = Integer.parseInt(count) + 1;

count = new Integer(c).toString();

settings.put(pageKey,count);

// 下面的语句没有使用 close 方法关闭流,有缺陷!

settings.store(new FileOutputStream(countFilePath),

"the page is accessed:");

}

catch(Exception e)

{

System.out.println(e.getMessage());

}

return count;

}

}

<wrap side="left"><font face="Times New Roman" size="3"></font></wrap>


编译 CountServlet.java 源文件,确保编译后生成的 class 文件存放在了 < tomcat 的安装目录 >\webapps\it315\WEB-INF\classes 目录中。

2 )修改 < tomcat 的安装目录 > \webapps\it315\WEB-INF\web.xml 文件,在其中的相应位置处增加如下两段内容:

<servlet>

<servlet-name>CountServlet</servlet-name>

<servlet-class>CountServlet</servlet-class>

</servlet>

……

……

<servlet-mapping>

<servlet-name>CountServlet</servlet-name>

<url-pattern>/servlet/CountServlet</url-pattern>

</servlet-mapping>

保存 web.xml 文件后,重新启动 Tomcat

3 )在任何计算机上的任何 HTML 页面中只要加入如下语句:

<img src="http:// 可对外访问的主机地址 :8080/it315/servlet/CountServlet">

就可以统计和显示该页面的访问次数了。在 <tomcat 安装目录 >\webapps\it315 目录中编写一个名为 count.html html 文件,如 例程 5-11 所示

例程 5-11 count.html

<wrap side="left"><font face="Times New Roman" size="3"></font></wrap>


<meta http-equiv="Content-Type" content="text/html;charset=GB2312">

本网页已被浏览了 <img src="http://localhost:8080/it315/servlet/CountServlet"> 次。

<wrap side="left"><font size="3"></font></wrap>


在浏览器地址栏中输入如下地址:

http://localhost:8080/it315/count.html

浏览器中显示的结果如图 5.18 所示。

如何实现图像访问计数器

<shape id="_x0000_i1026" style="WIDTH: 363.75pt; HEIGHT: 201pt" type="#_x0000_t75"><imagedata src="file:///C:%5CDOCUME~1%5Cgaocao%5CLOCALS~1%5CTemp%5Cmsohtml1%5C01%5Cclip_image004.png" o:title=""><font size="3"></font></imagedata></shape>

5.18

刷新浏览器的访问几次,可以看到图片中的数值随之增长。

如何实现图像访问计数器


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论