设计一个中间件的访问日志组件

对任何一个系统,一个强大的日志记录功能是相当重要且必要的,根据日志的记录可以及时掌握系统运行时的健康状态及故障定位。然而作为web容器存在另外一种日志——访问日志。访问日志一般会记录客户端的访问相关信息,包括客户端ip、请求时间、请求协议、请求方法、请求字节数、响应码、会话id、处理时间等等。通过访问日志可以统计访问用户的数量、访问时间分布等规律及个人爱好等等,而这些数据可以帮助公司在运营策略上做出抉择。

如果让你来设计一个访问日志组件你会如何来设计?你应该很快就会想到访问日志的核心功能就是将信息记录下来,至于要记录到哪里、以哪种形式来记录我们先不管,于是很快想到面向接口编程定义一个接口AccessLog,方法名就命名为log吧,需要传递参数包含请求对象和响应对象,如下,

public interface AccessLog {

public void log(Request request, Response response);

}

定义一个好的接口是一个良好的开始,接下去要考虑的事是需要哪些类型的组件,针对前面的记录到哪里、以哪种形式记录我们最熟悉也最先想到的肯定就是以文件形式记录到磁盘里,于是我们来实现一个文件记录的访问日志组件吧。

public class FileAccessLog implements AccessLog{

public void log(Request request, Response response){

String message=request与response中的值拼组成你需要的字符串。

try {

Charset charset = Charset.defaultCharset();

PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(

new FileOutputStream("c:/accesslog.log", true), charset), 128000),

false);

writer.println(message);

writer.flush();

} catch (IOException e) {

}

}

}

看起来这是一个简单且不错的文件记录访问日志组件的实现,起码用于例子展示让人一看就觉得简单明了,采用PrintWriter对象用于写入操作,而且使用了BufferedWriter添加一个缓冲作用(使用Buffered如何能达到缓冲效果,如果你忘了请看我前面写的缓冲装置相关章节,看完一定会对缓冲有一个深入的了解),之所以把缓冲大小设置为128000是经验得出来的一个适合值,OutputStreamWriter则可以让字符进行编码,此处使用Charset工具提供的默认编码,FileOutputStream则指定写入的文件路径及文件名,而true表明追加日志而非覆盖。

假如你觉得用sql语言来统计日志的信息让你更加得心应手,那就写到文件就不符合需求,我们需要另外一个实现,通过jdbc将日志记录到数据库中。于是你必须另外建一个JDBCAccessLog类并重新实现log方法,使用JDBC操作数据库大家是最熟悉不过的了,受篇幅限制不详细写实现细节,但有一个前提是你必须跟数据库约好创建一张特定的表且表的结构要根据访问信息定义好。

public class JDBCAccessLog implements AccessLog{

public void log(Request request, Response response){

通过JDBC把request和response包含的访问信息组成一个sql语句插入数据库。

}

}

你还可以根据自己的需求定制各种各样的访问日志组件,只需实现AccessLog接口。但有时可能你会使用多个访问日志组件,例如又写入文件又持久化到数据库中,这时我们还是提供一个设配器给他吧,

public class AccessLogAdapter implements AccessLog {

private AccessLog[] logs;

public AccessLogAdapter(AccessLog log) {

logs = new AccessLog[] { log };

}

public void add(AccessLog log) {

AccessLog newArray[] = Arrays.copyOf(logs, logs.length + 1);

newArray[newArray.length - 1] = log;

logs = newArray;

}

public void log(Request request, Response response) {

for (AccessLog log: logs) {

log.log(request, response);

}

}

}

经过适配器的适配,log方法已经变成了遍历去调用多个访问日志组件的log方法,而适配器提供给对外的接口仍然是一个log方法,编写如下测试类log的调用将会分别向文件及数据库记录下hello tomcat。

public class Test{

public static void main(String[] args){

AccessLog accessLog = new AccessLogAdapter(new FileAccessLog());

accessLog.add(new JDBCAccessLog());

accessLog.log(new Request("hello tomcat"),new Response());

}

}

经过以上的设计一个良好的访问日志组件就已经成型,而这也是Tomcat的访问日志组件的设计思路,而且Tomcat考虑到模块化和可配置扩展,它把访问日志组件作为一个管道中的一个阀门(管道机制忘了的朋友请看前面管道机制章节),这样就可以通过Tomcat的服务器配置文件配置实现访问日志记录功能,可以在任意容器中进行配置。

时间: 2024-10-25 22:48:21

设计一个中间件的访问日志组件的相关文章

Android 设计一个菱形形状的Imageview组件.

网上没有资料,特来请教下大神 Android 设计一个菱形形状的Imageview组件. >> android 这个答案描述的挺清楚的:http://www.goodpm.net/postreply/android/1010000007107851/Android设计一个菱形形状的Imageview组件.html

【Go】类似csv的数据日志组件设计

原文链接:https://blog.thinkeridea.com/201907/go/csv_like_data_logs.html 我们业务每天需要记录大量的日志数据,且这些数据十分重要,它们是公司收入结算的主要依据,也是数据分析部门主要得数据源,针对这么重要的日志,且高频率的日志,我们需要一个高性能且安全的日志组件,能保证每行日志格式完整性,我们设计了一个类 csv 的日志拼接组件,它的代码在这里 datalog. 它是一个可以保证日志各列完整性且高效拼接字段的组件,支持任意列和行分隔符,

访问日志格式的自定义

在第一小节中经过几步一个访问日志组件已成型,但为了增加用户自定义能力我们还是要继续做点事,对于用户自定义的实现最经典的做法就是引入变量表示,例如定义%a表示远程主机IP.%A表示本机IP等等,然后在写入之前用相应逻辑把变量替换成相应的值写入日志.这节我们来实现日志格式的自定义支持. 整个过程其实是先自定义变量组,再逐个把变量替换成相应值,最后把替换后的值写入文件.由于需要实现很多不同的变量,所以定义一个接口用于约束所有变量添加操作的定义,定义一个addElement方法,通过从request和r

Log4j日志组件的使用

日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录.在apache网站:jakarta.apache.org/log4j 可以免费下载到Log4j最新版本的软件包. 1.新建一个Java工程,导入包log4j-1.2.17.jar,整个工程最终目录如下 2.src同级创建并设置log4j.properties 1 ### 设置### 2 log4j.rootLogger = debug,stdout,D,E 3 4 ### 输出信息到控制

Nginx 访问日志轮询切割

默认情况下 Nginx 会把所有的访问日志生成到一个指定的访问日志文件 access.log 里,但这样一来,时间长了就会导致日志个头很大,不利于日志的分析和处理,因此,有必要对 Nginx 日志,按天或按小时进行切割,使其分成不同的文件保存. [[email protected] conf]# cat cut_nginx_log.sh #!/bin/bash Dateformat=`date +%Y%m%d` Basedir="/usr/local/nginx" Nginxlogdi

自定义nginx访问日志和内置变量使用

自定义nginx访问日志和内置变量使用 安装第三方echo模块后查看内置变量 内置变量 1.$args 用户在浏览器中查找的相关参数(uri中?之后的字段)2.$document_root 站点根目录所在的位置3.$document_uri 去除url中域名部分后所剩下的目录4.$host 所访问的主机5.$http_user_agent 客户端所使用的浏览器6.$http_cookie 客户端的cookie信息7.$limit_rate 客户端的下载速率0表示不限制速度 server { se

2015第30周四Java日志组件

Java 日志 API 从功能上来说,日志 API 本身所需求的功能非常简单,只需要能够记录一段文本即可.API 的使用者在需要进行记录时,根据当前的上下文信息构造出相应的文本信息,调用 API 完成记录.一般来说,日志 API 由下面几个部分组成: 记录器(Logger):日志 API 的使用者通过记录器来发出日志记录请求,并提供日志的内容.在记录日志时,需要指定日志的严重性级别.当 程序中需要记录日志时,首先需要获取一个日志记录器对象.一般的日志记录 API 都提供相应的工厂方法来创建记录器

【转】java日志组件介绍(common-logging,log4j,slf4j,logback )

common-logging common-logging是apache提供的一个通用的日志接口.用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库.当然,common-logging内部有一个Simple logger的简单实现,但是功能很弱.所以使用common-logging,通常都是配合着log4j来使用.使用它的好处就是,代码依赖是common-loggin

日志组件介绍(common-logging,log4j,slf4j,logback)

common-logging common-logging是apache提供的一个通用的日志接口.用户可以自由选择第三方的日志组件作为具体实现,像log4j,或者jdk自带的logging, common-logging会通过动态查找的机制,在程序运行时自动找出真正使用的日志库.当然,common-logging内部有一个Simple logger的简单实现,但是功能很弱.所以使用common-logging,通常都是配合着log4j来使用.使用它的好处就是,代码依赖是common-loggin