ITPub博客

首页 > 应用开发 > IT综合 > (译)一个用于MVC模式web应用的基于过滤器的情景预知跨站日志框架

(译)一个用于MVC模式web应用的基于过滤器的情景预知跨站日志框架

原创 IT综合 作者:freeelancer 时间:2006-03-31 10:00:37 0 删除 编辑

这篇论文描述的是一个在跨站点的Web session中收集用户行为信息的框架的定义和开发。该框架将采用MVC(Model View Controller)模式,并应用于Web开发中,它能纪录sessions、clicks(点击)、impressions(印象)的信息。并且优秀的设计使它能非常方便地实现与部署环境的整合。

[@more@]


Adrian E. Ridner, Mei-Ling L. Liu
California Polytechnic State University, San Luis Obispo
Computer Science Department
California, U.S.A.
mliu@csc.calpoly.edu
摘要 这篇论文描述的是一个在跨站点的Web session中收集用户行为信息的框架的定义和开发。该框架将采用MVC(Model View Controller)模式,并应用于Web开发中,它能纪录sessions、clicks(点击)、impressions(印象)的信息。并且优秀的设计使它能非常方便地实现与部署环境的整合。
关键词:mvc框架、网站开发、WEB日志

1.导言

对于网站服务商来说,最希望获得的当然是对每个来访session的行为统计了.这样的统计工具现在也有许多,像rcounter[12], statCounter[13], webStats[14]之类,他们可以用来统计访问量(measuring traffic) 并监测站点的使用(monitoring site usage).这些基于计数器和服务器访问文件(server access files)的工具,能提供的信息就是站点访问量或某个访问者的一些特征(如他使用的浏览器和screen resolution)这种信息尽管有用,但是仅能于特定的页面或站点获得,而不能从用户跨页面或跨站点的完整session中获得。
本文描述了一个Web应用程序的日志框架,它是采用MVC模式,在J2EE Web Application Servers[4].下开发的。这个框架的设计,可以记录发生在多个站点上的事件, 这些被纪录的事件都是环境敏感的,也就是说他们都是用户根据某站点上下文自定义的,而且配置该框架可以不对要记录的Web应用程序源代码做任何的修改。

1.1 MVC web 应用程序框架
MVC是著名的交互式结构设计模式,MVC模式很适合于J2EE Web应用程序开发。 这些应用程序由以下3种组件组成:model(模型)组件通过Java beans实现,view(视)组件由JSP来表现,还有controller(控制器)组件由一个或多个servlets[6]组成。每个组件都有自己的用处:请求控制器(controller)处理请求任务的分派,view组件表达业务逻辑,而model组件则包含业务逻辑。
当前有许多工具提供基于MVC模式的java web应用程序开发。在这些工具中,最流行的应该是开源项目Apache Struts[2,7]了。 在Struts框架中每个Web应用程序都由一些配置描述器联合而成,这些配置描述器是用来在应用程序配置时初始化servlets和taglibs(tag libraries)等资源的。配置描述器通常就是一个扩展标记语言文件web.xml。使用struts框架来搭建Web应用程序的基本步骤如下:
1. 用JSP文件实现数据入口表单;
2. 实现一个或多个派生ActionForm,缓存JSP页面和Actions(servlet)之间的交换数据;
3. 创建一个XML文档来定义应用程序的校验机制;
4. 实现一个或多个Action来响应表单的提交任务;
5. 创建一个struts-config.xml来构建表单与actions的对应关系;
6. 创建或更新web.xml来调用Struts需要的ActionServlet、taglibs;
Struts的成功也促进了其他框架的发展,其中包括Maverick[10]、WebWork[11]这样流行的框架。这三个框架都支持以灵巧著称的filter模式,filter可以很简单的就配置到应用程序中。


1.2.J2EE Filters
在J2EE Web应用程序中,filter是一个可以动态截取requests和responses,并转换或提取其中信息的组件。Web应用程序可以设置成无论何时,HTTP 服务器在接收到对某一特定资源(通过request的URL来确定)的请求时都自动执行一个或多个filter代码。
当filter截取到一个请求时,它也就是在访问一个包含了HTTP request和response的Java 对象。当HTTP request访问一个被filter保护(隔离)的资源时,这个filter,也是一个Java对象,就被执行了。Filter能够检查并修改 HTTP 响应的头(header)及数据、阻挡请求、抛出异常、或是调用另一个filter。所以Filter能够高效地用于登陆、调试、实现加密技术、数据压缩。
J2EE filter在我们的登陆框架中扮演了非常重要的角色。

2. 日志框架设计
我们的日志框架由一个应用程序接口(API),一个J2EE filter集组成。API为各种类型的事件实现了其特定的日志功能,它的主要组成部分有一个EventLogger接口、一些类、终端日志纪录器。通过良好的设计,日志记录器(logger)类可扩展到适应用户特定的日志需求。另外,本框架提供了一系列的filter,其中每一个filter都可感知特定的日志记录器。也就是说为了创建正确的日志记录器,系统有能力、也有必要创建一个LoggerManager(a factory)。一旦日志记录器被创建,它就会调用自己的日志记录方法把适当的日志记录写入到文件中。

2.1.EventLogger 接口 EventLogger接口包含有日志事件最一般的属性。该接口定义了一个日志纪录方法,它接收一个对象作为参数,然后把这个对象转型为适合日志记录器的事件对象。每个事件对象都有个更新文件句柄的方法,文件句柄是一个Java句柄对象,负责向文件系统写入日志数据。EventLogger接口还定义了一个可初始化所有数据库关联对象的方法,给用户备用。最后,该接口定义了两个方法来保存应用程序的路径和应用程序日志的路径。

2.2. BaseEventLogger
BaseEventLogger是个继承自EventLogger接口的抽象类。它是用来向所有日志记录器(logger)提供统一方法的。

2.3. BaseClickLogger
在web应用程序中最常见的事件应该算鼠标单击了(例如:点击某一链接)。BaseClickLogger是BaseEventLogger的子类,不过它并不是情景预知(context-aware)的。它包含了子类记录各种“点击”事件所需要的函数功能,还有对updateFileHandlerIfNeeded和源自EventLogger的log函数的基本实现。


2.4. BaseSearchLogger
站点一般提供了某种形式的搜索引擎,来让用户执行搜索功能。BaseSearchLoggerEvent抽象类可以记录每个引擎的日志,它继承于BaseEventLogger。这个抽象类会被用户自定义的子类继承,并且是环境敏感的(context-aware):意思是子类将于特定的web页面中实现,并能为特定的搜索引擎记录日志。


2.5. ClickToFormLogger
这个类包含了记录用户点击外部页面(也叫表单)链接的功能函数。ClickToFormLogger是BaseEventLogger的子类。该类提供了一个叫assignGuid()的函数。这个函数为点击事件产生一个全局唯一的标识(global unique identifier简称为GUID),并且包含这个日志记录上已有事件的GUID。当用户链接到一个外部站点时,GUID(global unique identifier)将作为一个HTTP GET参数传送过去。GUID服务作为一个标识(tag)来实现同一session跨站点事件的关联。


2.6. ImpressionsLogger
在web开发术语中,Impression(印象),指受用户要求的网页或广告图像的每一次显示, 就是一次印象。例如,在某页显眼的地方显示一副图片,引起登陆者对特定商品的访问,当然这种Impression(印象)的效率才是网站服务商所感兴趣的。ImpressionsLogger类继承自BaseEventLogger,并且也能被用户实现来监测指定Web应用程序所有与印象相关的事件。


2.7. ClickLogger
ClickLogger类几乎继承了BaseClickLogger所有的函数,并能被用户自定义来记录指定Web应用程序的单击事件。


2.8. SearchLogger
SearchLogger类继承了BaseSearchLogger的函数,并能被用户实现来纪录指定Web应用程序的搜索事件。


2.9. ClickLoggerFilter
这个类实现了Java Filter接口。它包含了点击事件发生时,filter应具有的所有行为。


2.10. SearchLoggerFilter
这个类也实现了Java Filter接口。当搜索事件发生时,它来充当filter处理相应事务。


2.11.The LoggerManager
LoggerManager实现了每个日志记录器对象唯一的设计模式;也就是说,它可以保证Web应用程序中每种日志记录器只有一个实例。LoggerManager通过反射机制(reflection)来实现这个功能。当filter请求分配日志记录器时,相应的类对象(如 ClickLogger.class)就会被传入到LoggerManager.getInstance(Class c)函数中。LoggerManager有一个本地的映射表(Map),它维护着所有已存在的单件对象(singleton instances)。首先它尝试用传入的类对象作为关键字,在映射表中查询。如果存在一个相应的值,那一定就是要申请的日志记录器的一个实例了。如果映射表中没有相匹配的值,LoggerManager将为传入的类对象创建一个新实例,然后把创建的新实例插入到映射表中。


2.12. LoggerRotator
LoggerRotator类的实现采用了策略(strategy)模式。策略(strategy)模式定义了一系列算法(algorithms),并且所有算法可互相替代。所以,这种设计模式可以根据需要变换算法[1]。在LoggerRotator中,这种设计模式用来提供日志文件间的松耦合关系(请查看下章“Log file granularity”)。LoggerRotator类有一个运用策略(strategy)模式来保存日志文件的updateFileHandlerIfNeeded函数。也就是说,当前日志文件的格式、名称、保存位置都是根据站点定义的,并且能在不影响调用代码的情况下轻松修改。


2.13. LogIterator
与LogRotator相似,LogIterator也使用策略(strategy)模式来实现在它创建的日志文件中迭代。这个类实现了Java Iterator接口。


3. 日志框架的实现
为了让日志框架的安装能更简便些,我们创建一个Apache Ant [15]任务来编译所有的源代码,并把它们打包到一个jar文件中。


3.1. Filter的XML配置
在部署我们的框架时,Web应用程序必须配置一些必要的filter。下面列出的XML代码,简单地在WEB-INF/web.xml文件中添加一个ClickLoggerFilter的映射,就实现了一个filter在Web应用程序中的配置:


ClickLoggerFilter


com.remilon.filters.ClickLoggerFilter




ClickLoggerFilter


/exec/*


上面的XML代码指定任何一个对Web页面的请求,只要URL中含有“/exec”子串,都会首先被ClickLoggerFilter“过滤”。这个例子假定该应用程序中所有有意义的页面,URL中都含有/exec/路径,像http://somesite.com/exec/logon.jsphttp://othersite.com/blah/hi/exec/other.jsp。大部分的Web应用程序都已采用这种层次设定URL[4]的方法。


每个日志记录器至少要映射到一个filter上。因此,如果一个搜索日志纪录器被激活了,配置文件就要为SearchLoggerFilter类做如下的修改:

有两件事需要注意:首先因为一个应用程序的配置文件中出现了两个过滤器(filter)的定义,所以两个过滤器的映射都会对所有该应用程序的HTTP请求起作用。例如:URL 是http://something.com/blah/exec/search?id=1,ClickLoggerFilter和SearchLoggerFilter就会按照它们在web.xml文件[5]中定义的顺序依次执行:ClickLoggerFilter将会侦测URL中的/exec映射,然后进行处理;而SearchLoggerFilter将会侦测URL中的/search子串,然后进行处理。


其次,添加的XML代码行是标准的J2EE过滤器映射,能够在所有支持Servlet 2.2版本的web服务器上执行,像:Apache Tomcat[7]、WebLogic[8]、还有Resin[3,8]。

3.2. 判定session的起始
由于我们的框架要能够纪录整个session的事件,所以判定session的起始显得非常重要。在session开始时,会产生一个唯一的标示——全局用户ID(guid)[16]——来标记整个session中发生的事件。判定session开始的功能在BaseClickLoggerFilter中通过查询HTTPRequest对象来实现,代码如下:

…..
httpReq = ((HttpServletRequest)request);
session = httpReq.getSession();
if (session.isNew( ))
{
this.logNewSession(httpReq, session);
}


判定session的结束就要复杂得多了。用户突然离开相应的站点,关闭浏览器窗口,失去他/她的网络连接,或进行其他操作而不注销都会导致session的结束。典型的解决方案就是引进超时概念(time-out concept),这样一个session超过一段时间没有任何操作就会认为被关闭了[5]。该框架的目的就是,不管怎样,通过纪录的日志信息都能分析出用户(由guid来区别)在任何一个打开日志功能的站点上的最后一次操作。


3.3. 跨站点行为的跟踪
该框架最大的创意就是对跨站点行为的跟踪。此功能的实现也需要一个过滤器(filter),响应所有的HTTP请求:它在请求的URL后面追加一个guid。例如:当用户点击如下链接时http://gotoothersite.com/exec/browse.jsp,该过滤器就会截取这个请求,并绑定一个随机的guid到它的URL上,产生如下的链接:http://gotothersite.com/exec/browse.jsp?guid=z8r4u7dn459skmdn45tjdfls93k54mf0s8


另外还必须满足下面两个条件:
l gotoothersite.com服务器上的Web应用程序也必须使用相同的日志框架。该框架会侦测到包含在HTTP请求串里的guid参数,并把这个guid与新分配的session(在gotoothersite.com上的)联系起来。这种联系必须在gotoothersite.com上保存。
l 当截取过滤器运行时,它也必须把用户本地ID(译者注:session ID)和发送到gotoothersite.com服务器的GUID的联系记录下来。
满足这两个条件,在以后的分析中数据就会被正确的关联到一起。
实现以上要求的代码大致如下:

{


String guid = this.assignGuid( );
String msg = QUOTE + guid + QUOTE +
SEP + sessionSiteId + SEP +
linkIdStr + SEP + dbSessionId
+ SEP;
msg += this.quoteIfNotNull
(httpReq.getHeader("Referer"));
msg += QUOTE + new
String(httpReq.getRequestURL( ))
+ QUOTE + SEP;
msg += this.quoteIfNotNull
(httpReq.getQueryString( ));
java.sql.Timestamp now = new
java.sql.Timestamp(
new Date( ).getTime( ));
msg += now.toString( );
// log sql statement
ClickLogRecord logRecord = new
ClickLogRecord(Level.FINEST, msg);
clicktoformLogger.log(logRecord);
log.finer("Logging click to form end");
httpReq.setAttribute("guid", guid);
return httpReq;
}
private String assignGuid( )
{
String guid = new
RandomGuid(true).toString( );
return guid;
}

3.4. 日志文件粒度
在我们的框架中,数据是在整个Web应用程序生命周期里不断收集的。如果纪录数据的文件没有不断重用的话,数据量将是非常庞大的。在我们的实现中,日志文件是以基于小时的格式维护的:每隔一个小时纪录给定日志事件的文件就会被重用。日志文件按照如下格式来设置:/base/logger/dir/YEAR/MONTH/DAY/HOUR。例如:文件/base/logger/dir/2004/01/03/22就收集了2004年1月3号22时的数据(从晚上10点到晚上11点)。


4. 产品部署
我们在6个互相链接的站点上部署了一个日志框架的原型,来评估该框架的(i)部署方便性,(ii)性能表现,和可测量性。该框架配置在6个运行于Resin应用服务器上的web应用程序里。这些程序都是一些职业学校的Web站点。每日有超过4万的session总访问量。


4.1.服务器配置
这些Web应用程序运行于分散的服务器主机上。每个应用程序都采用Struts框架,并具有相当大的代码基底。每台服务器机器都是双核PIII 1.8 GHZ处理器,2 GB 内存和200 GB硬盘。


4.2. 安装需求
该框架应该装在每个服务器主机上。每个Web应用程序都要有一个存放jar文件的库文件夹。安装过程大致如下:


l 运行一个Ant任务,编译所有的源代码,并打包成一个jar文件。
l 将打包的jar文件(remilon-logging.jar)拷贝至webapp/lib目录下
l 在WEB-INF/web.xml文件中添加ClickLoggerFilter的映射
l 重启Web应用程序服务器


用户可以随意地编写他们自己的过滤器,扩展该框架来实现其他的日志记录器功能。不管怎样,以上jar文件的安装和对XML配置文件的修改,已足以自动激活我们的日志框架了。
在我们的测试下,该日志框架运行了近3天,没有发生什么重大的问题。主要的问题像数据量过大,需要同步运行,需要改进缓存技术;但是大部分时间该原型都能在不影响Web站点正常工作的情况下执行,并收集到期望的数据。对站点性能的影响并不大。

5. 结论
本文介绍了一个基于过滤器的,情景预知的,跨站日志框架;它能整合到所有基于MVC模式的Web应用中。我们的日志框架对事件进行记录,几乎不影响Web应用程序性能,并且完全不用对Web应用程序的源代码做任何修改。该框架是基于API的,能根据用户需要做出扩展,也能完成更深层次的工作。


6. Furture work
本文描述的框架还在不断完善着。大家还在讨论着对于可选的日志记录是通过行为,还是通过用户来选择过滤规则。

参考资料:1. Gamma, E. et al. Design Patterns. Addison-Wesley.1995.
2. Goodwill, J. and Hightower, R. Professional Jakarta Struts. John Wiley & Sons. 2003.
3. Hightower, R, and Gradecki, J. Mastering Resin. Wiley Publishing. 2003.
4. Johnson, R. J2EE Design and Development. Wiley Publishing.. 2003.
5. R. Eckstein, Java Enterprise Best Practices, O’Reilly & Associates, 2002.
6. Sun Microsystems, JSP and Servlet Specification,
http://java.sun.com/products/, 2003
7. The Apache Software Foundation, Struts,
http://jakarta.apache.org/struts/, 2003.
8. BEA Systems, “WebLogic Application Server,
http://www.bea.com/, 2003.
9. Sun Microsystems, Java Filter Specification,
http://java.sun.com/products/servlet/Filters.html, 2003.
10. sourceforge.net, Maverick MVC Framework,
http://mav.sourceforge.net/, 2003.
11. WebWork, WebWork MVC Framework,
https://webwork.dev.java.net/, 2003.
12. NooLab Corporation, Rcounter,
http://rcounter.noonet.ru/, 2004.
13. StatCounter, StatCounter, http://www.statcounter.com/,2004.
14. NetLogics, WebStats,http://webstats.netlogics.nl/default.asp, 2004.
15. Apache Foundation, The Apache Ant Project,http://ant.apache.org/, 2004.
16. M. Mnich, RandomGUID,
http://www.javaexchange.com/aboutRandomGUID.html,2002.

名词表
单件对象(singleton instances)
映射表(Map)
strategy(策略)模式
超时概念(time-out concept)
code base 代码基底
情景可预知的(context-aware)

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/1693784/viewspace-824235/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
下一篇: 没有了~
请登录后发表评论 登录
全部评论
  • 博文量
    1
  • 访问量
    5301