java如何对实现⽇志过滤敏感信息_Java原⽣⽇志(下)抽象类的使用
原⽣
1 Handler使⽤和设置
虽然从使⽤上来说Logger可以单独使⽤,但并不代表Logger能够独⽴完成⽇志的⼯作。⽇志的处理⼯作有两⼤部分组成,第⼀个部分是⽇志的记录⼯作,这时Logger的主要⼯作,它主要的作⽤是将外界信息转化成⽇志信息并进⾏初步的管理,我们可以理解为⽇志信息的收集和创建。第⼆个部分是⽇志处理⼯作,⽇志处理⼯作主要对Logger中已经记录的信息进⾏处理导出,只有通过导出后,我们才可以获取⽇志信息,我们可以理解为⽇志信息的处理和发送。在⽇志体系中Logger和Handler是⼀种聚合关系,⼀个Logger中可以包含⼀个或者多个Handler。
Handler处理的功能范围包括⽇志信息的编码、格式、过滤、以及设置⽇志级别。Handler本⾝不能设置⽇志导出的⽬的地,也没有提供相关的⽅法进⾏设置,Handler本⾝还是⼀个抽象类,必须使⽤Handler的⼦类来完成。
Handler⼦类对⽇志的导出分类两种类型,⼀种向内存缓冲导出,⽤MemoryHandler类来实现。另⼀种是IO导出,IO导出由下⾯三个类来完成:
· ConsoleHandler:可以将⽇志信息发布到控制台上,由输出。
· FileHandler:可以将⽇志信息输出到⽂件中,也可以写⼊到⽂件轮换集中。
· SocketHandler:将⽇志信息发布⽹络连接中。
如果我们想要将⽇志信息导出到⽂件中,我们只能选择FileHandler来完成。在创建FileHandler时候有五个构造⽅法供我们选择:
1.FileHandler()
2.FileHandler(String pattern)
3.FileHandler(String pattern, boolean append)
4.FileHandler(String pattern, int limit, int count)
5.FileHandler(String pattern, int limit, int count, boolean append)
在这些构造⽅法中,patter是⽤字符串表⽰的⽂件路径,append⽤于表⽰⽂件是否为追加模式。limit表⽰⽇志⽂件最⼤的字节数,count 表⽰⽇志⽂件的个数。使⽤不同构造⽅法创建的⽇志处理器,它们的功能各不相同。如果我们没有设置append参数,它默认为覆盖模式,这样会造成就⽇志的覆盖。所以如果我们想让⽇志处理追加状态,需要使⽤第3或者第5个构造⽅法,并将append参数设置为true。
在⼀些⽣产环境中,系统⽇志记录的数量⾮常多,这样会造成⽇志⽂件过于庞⼤,如果⽇志过⼤,⽇志是不利于查看,甚⾄⽆法⽤普通⼯具打开查看。这时我们需要构造⽅法中的第4和第5个,可以将⽇
志信息导出到⽂件集中,当⽇志⽂件的字节数超过limit时,⽇志⽂件会重新建⽴⼀个新的⽂件,并向新的⽂件中写⼊,例如我们指定的⽇志⽂件为"log.log",在导出⽂件集时,会默认将第⼀个⽇志⽂件修改为"log.log.0"以此类推,最⼤为count。当FileHandler导出⽇志⽂件集的数量超过了count时,再次导出的⽇志会从第1个⽇志⽂件开始写起,并将原有的⽇志信息进⾏了覆盖,并会⼀直重复这个过程。
在下⾯⽰例中,我们演⽰了FileHandler和Logger结合后,将⽇志信息输出到⽂件中。
在上述⽰例中,我们创建的⽂件处理器,可以将⽇志信息导出到⽂件集中。在运⾏程序⽰例后,我们依然可以看见控制台上⽇志的打印情况。但在⽂件所在位置上,我们可以看到创建了新的⽂件"log.log.0",我们使⽤⽂件查看⼯具打开后,⽇志⽂件内容如下图所⽰。
⽇志⽂件log.log.0
从⽇志⽂件内容中,我们可以发现,⽂件中的⽇志信息与控制台打印的信息格式不同,但内容更丰富。这是由于FileHandler采⽤的默认格式为XMLFormatter。
Java的⽇志体系中,提供两种基础⽇志格式:⼀种⽤XMLFormatter类进⾏封装XML格式,XML是⼀种扩展标记格式。在XML格式下,每⼀条⽇志⽤⼀对""标签表⽰。标签内出现的每⼀对⼦标签都表⽰⽇志中包含的信息名称,标签中的⽂本表⽰信息的内容。我们可以到⽇志的时间、等级、所在⽅法、以及Logger名称等详细的⽇志信息。
另⼀种是普通信息,这也是控制台所打印出来的信息,以SimpleFormatter类进⾏装封的简单基本信息。如果我们想让⽇志⽂件中的格式与控制台格式保持⼀致。我们可以通过Handler的setFormatter⽅法进⾏设置,如"setFormatter(new SimpleFormatter())"。
如果我们想构造出更复杂的格式,我们可以⾃⼰创建格式类,但必须继承Formatter抽象类(java.util.logging.Formatter,它是XMLFormatter和SimpleFormatter的⽗类)。
在记录⽇志的时候,我们可以通过Logger的 setLevel⽅法设置⽇志消息级别。在Handler中同样存在setLevel⽅法,并且中默认的⽇志级别也为info。
如果Logger和Handler中都设置了⽇志级别,Handler会被Logger所影响。被Logger所忽略掉的⽇志信息,Handler是⽆法导出的(Logger会先过滤符合级别的⽇志)。在下⾯⽰例中,我们演⽰了这⼀个过程。
在上述⽰例中,FileHandler的⽇志级别低于Logger,在运⾏程序⽰例时,我们发现控制台只输出了WARNING级别的⽇志。在导出的⽇志⽂件中,我们也只发现了WARNING级别的⽇志信息。⽇志⽂件"log.log"信息如下图所⽰。
⽇志⽂件log.log
如果FileHandler中设置的⽇志级别⾼于Logger中的级别,这样可以实现双层⽇志级别过滤。
2 Logger中的Handler
Logger作为⽇志的记录器,拥有记录⽇志的功能,Handler是⽇志的处理器,主要功能是设置⽇志的格式,并将⽇志导出。
每⼀个Logger可以包含⼀个或者多个Handler,这样⼀个Logger就可以同时向多个⽂件、多个⽹络端
以及控制台导出⽇志信息。如果Logger不包含⽇志处理器,⽇志记录器中记录的⽇志就⽆法被导出,外界⽆法观察到⽇志信息。
在默认的 Logger中,当我们将信息交由Logger记录时,默认会从控制台进⾏输出。这说明Logger中应该还有默认的Handler,并且是⼀个ConsoleHandler类型的处理器。在Logger中与Handler相关的⽅法有五个,如下表所⽰。
Logger中与Handler相关的⽅法
除了Handler的添加和删除⽅法外,getHandlers⽅法可以获得当前Logger中所有绑定的记录器,这样我们可以通过该⽅法获取并修改Logger中的Handler。剩下的两个⽅法涉及到⽗记录器中的Handler(在Logger⽇志体系中,每⼀个Logger对象都会有⼀个⽗Logger,如果我们想深⼊了解原因,可以参考LoggerManager中的说明)。
当我们创建了Logger时,⽆论我们是否给新建的Logger添加Handler,它都会继承⽗记录器的消息级别,并且会将⽇志消息发送给⽗记录器。⽗记录器中的Handler默认是⼀个ConsoleHandler类型的Handler,所以当我们创建的Logger在记录⽇志后,都会输出到了控制台。在没有停⽌使⽤⽗记录器的Handler时,getUseParentHandlers⽅法永远返回true。同样的,我们可以调⽤setUseParentHandlers⽅法,停⽌使⽤⽗记录器Handler。
由于⽗Handler的存在,在⼀些情况下,它会给我们造成⼀些错觉,当我们讲Logger的消息权限设置在INFO以下的级别时,我们会发现setLevel⽅法⽆效,控制台上⽆法显⽰INFO级别以下的消息,造成这个原因并⾮setLevel⽅法⽆效,⽽是⽗Logger中的Handler默认级别为INFO,它会再次过滤⼀次。如果要解决这个问题,最直接的⽅法有两种,⼀种是直接修改⽗Logger中的Handler,另外⼀种⽅法为停⽌使⽤⽗Handler,给当前Logger添加⼀个消息级别的Handler,在下⾯程序⽰例中,我们演⽰了这两种⽅法。
在logging⽅法中记录了三个等级的⽇志信息,其中最低级的消息为CONFIG消息。其它三个设置⽅法⽤来设置Logger的记录消息的级别以及Handler处理消息的级别,其中defaultHandler⽅法中没有设置任何Handler,直接设置了消息记录的级别。在mian⽅法中,我们对⽐了三种设置,对⽇志记录以及处理的影响。
通过运⾏结果我们可以观察到,当只设置Logger记录⽇志等级时,INFO以下的信息是⽆法正常的被输出到控制台,⽽另外两种设置⽅法均可。
但要注意,所有新创建的Logger在没有指定⽗Logger时,默认的⽗Logger是⼀个没有名称的Logger,它是所有Logger的⽗Logger。这意味着,只要我们修改了它的Handler级别,其它Logger都会受到影响,所以我们尽量使⽤useDiyHandler中的设置⽅法。
3 过滤器Filter和LogRecord
设置⽇志管理级别(Logger级别)和⽇志处理级别(Handler)虽然⼀定程度上可以对⽇志信息进⾏过滤,但是如果要想加⼊更为精确的信息过滤,就需要使⽤到⽇志的过滤器。⽇志过滤器可以过滤敏感词汇。
在Logger和Handler中都可以进⾏过滤器Filter的设置,它们在各⾃的环节中起到的作⽤是⼀样的。
Filter是⼀个接⼝,在Java中并没有提供实现类,要实现过滤器功能,需要我们⾃⼰实现,这⼀点与File中的名称过滤器是相似的。接⼝Filter位与java.util.logging包中,该接⼝只有⼀个抽象⽅法⽤于⽇志的过滤的判断:
boolean isLoggable(LogRecord record):当⽅法返回true时,表⽰⽇志可以被记录或者被发布。
isLoggable ⽅法的参数LogRecord是⼀个真正的⽇志消息对象,它封装了⽇志消息的所有信息,并提供了修改⽅法。我们在使⽤Logger 记录⽇志消息的时候,建议使⽤log(LogRecord record)⽅法。⽆论任何级别、带有错误的消息,都可以封装在LogRecord对象中。在
Logger类中,所有的消息添加,最终都有该⽅法完成。在下⾯程序⽰例中,我们先演⽰LogRecord的使⽤。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论