上一篇里,笔者将DAO做了一个通用的实现,不过在继续之前,我们好像忘了些什么。就是做任何程序都不可缺少的东东,一个对程序的功能没什么用,很容被遗忘,但是每个方法里都需要有的东西,那就是日志。
笔者以往的经验都是将Log4j配置到Spring中去用,顺着这一点,访问了下log4j的官网,进而看到了新东东log4j2,粗略地看了一下介绍:比log4j更好的性能,做了些logback的实现甚至还解决了些logback的固有的问题,支持多种facade框架。听起来还不错,于是动了把这玩意儿加到Spring中的想法,到网上去搜娄了一翻后。。。
好吧,我承认东西很少,只能是苦读官方的英文文档加debug状态看源码了。
在log4j2的官网http://logging.apache.org/log4j/2.x/上,瞅一眼左侧的导航栏,大致都点进去看一下:API里说的需要JDK1.5以上,Architecture里的类架构图,以及与log4j的集成或转换等等。这些都不重要,因为目前没有用到,需要时候再来看不迟。我们的重点是Configuration.
进入Configuration页面,细读一下吧。
看到Configuration中所述,配置可以是xml形式,可以是json形式,也可以是编码的方式(Programmatically),我们要的是可以配到前面所写的由Spring@Configuration标注的ApplicationContext.java中的方式,当然就是编码方式,二话不说,直接按其所指,看看ExtendingLog4j
2 里怎么说。一堆诸如@Plugin的注解式配置,大喜。不过整了半天,没奏效。想想即使好用,配置到Spring中也是一件费力的事儿,还是去Debug吧。Log的用法还是这样:
Logger logger = LogManager.getLogger(this.getClass());
顺着这条藤,自是能摸到瓜的。LogManager中有Log4jContextFactory,用来选择生成LoggerContext.我们看到Context这个词,很容易就想到它是要干什么的:一个装载了很多通过名字得到的唯一单例的容器,所说的单例自然是Logger。正因如此,LogManager里的这个LoggerContext可以通过类名将logger一一对应。OK,不废话了,继续:在LoggerContext被实例化时,它有个属性Configuration也被同时实例化,这个实例是DefaultConfiguration类型.实例化后Facotry又将Context启动,调用了LoggerContext.start()方法,该方法会reconfiguraion()。这个reconfiguration()会进行系统下的配置找寻,也就是按照我们看到的官网中AutomaticConfiguration里所写的配置顺序进行找寻。(多一嘴:这里Debug过程中也确认了它在找系统默认ClassLoader中去找被注解所注的配置,而且看到我注解的类确实在ClassLoader里,至于为什么没有被加载,始终搞不明白)。继续Debug会看到最后它什么也没找到又加载一遍DefaultConfiguration。
然后笔者就开动脑筋,用Eclipse的代码提示功能去找用没有public的方法可以将配置重定向了。果不其然,找到了,方法如下:
Logger logger = LogManager.getLogger(this.getClass());
LoggerContext loggerContext =(LoggerContext)LogManager.getContext();
loggerContext.setConfiguration(new BaseConfiguration(){});
找起来很费劲的说,毕竟框架它做为通用性的库,考虑的东西需要很周到,我们目前要用的就只有这么些,直接贴上来为大家理解与使用更方便快捷。至于想更深层次看清它的朋友们,就不扰乱你们在Debug过程中的乐趣了。
上文BaseConfiguration类体中,直接那样匿名实现它就行,至于为什么用它而不用接口Configuration,想来你看了就知道,DefaultConfiguration很简单地写了构造方法继承了它就可以用,而如果匿名实现Configuration接口,会比较繁琐。笔者这样匿名写了个config()方法,直接returnthis
,在类体后面直接.config()调用会简易明了的展现这主要就是在做Configuration。不过试了一下,还是没好用。再去看DefaultConfiguration是如何做到的,如法炮制吧:覆写doConfigure()为空,因为在Configuration.start()后,它会被调用从而加载了很多appender把自己配制的都盖掉了。综上所述,上面代码中的最后一句就变成
loggerContext.setConfiguration(new BaseConfiguration(){
public BaseConfiguration config(){
setName("MyConfig");
Layout<?> layout = PatternLayout.createLayout("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n",null, null, null);
Appender<?> appender = ConsoleAppender.createAppender(layout, null, "SYSTEM_OUT", "Console", "true");
appender.start();
addAppender(appender);
LoggerConfig root = getRootLogger();
root.addAppender(appender, null, null);
String levelName = System.getProperty("org.apache.logging.log4j.level");
Level level = levelName != null && Level.valueOf(levelName) != null ? Level.valueOf(levelName) : Level.ERROR;
root.setLevel(level);
return this;
}
@Override
protected void doConfigure() {}
}.config());
测试一下,对了,前面一直说某些操作没好用,是如何看出?答案是只需将所写代码的layout的Patten中的一些格式化参数换一下位置看看输出,是否按所配Layout输出来的就可以了。因为上文中的config方法内的代码完全是DefaultConfiguration构造方法中的语句,所以变一下layout如果控制台输出的字符串还是按原来的顺序打出,那它的配置还是DefaultConfiguration.以下四行代码放到普通JUnit4的@Test方法中,可以测试出logger确实是一个类名永远只得到一个实例,并且控制台输出的字符按照自己配置的layout输出来了。证明配置成功。
Logger logger = loggerContext.getLogger(this.getClass().getName());
Logger logger0 = loggerContext.getLogger(this.getClass().getName());
Assert.assertSame(logger,logger0);
logger.error("Test Error2");
下面就是将这个log4j2的配置放到Spring中了,我想看了第一篇的话,这个配置应该是很简单了,在Spring的@Configuration注解的ApplicationContext.java中,写一个@Bean注解的方法,Return出一个LoggerContext即可,这个LoggerContex就可以注入到任意Spring的Bean中以供该Bean作Log用。当然还可以生成个通用的Log
Bean. 那就贴上代码段如下:
@Bean
public LoggerContext log4j2Context() {
LoggerContext loggerCtx = (LoggerContext) LogManager.getContext();
loggerCtx.setConfiguration(new BaseConfiguration() {
public BaseConfiguration config() {
setName("webmodel-log-Config");
Layout<?> consolelayout = PatternLayout.createLayout(
"%d{HH:mm:ss.SSS} [%thread] %logger{36} %-5level - %msg%n",null, null, null);
Appender<?> consoleAppender = ConsoleAppender.createAppender(consolelayout,null, "SYSTEM_OUT", "Console","true");
Layout<?> fileLayout = HTMLLayout.createLayout("true", "Webmodel Error Log", "text/html", null, "x-small", "arial,serif");
String fileName =this.getClass().getResource("/").getFile().replace("/classes/", "/log/")+"systemErrorLog.html";
Appender<?> fileAppender = FileAppender.createAppender(fileName, "true", "false", "errorLog","true","true", "true", fileLayout, null);
this.addAppender(consoleAppender);
this.addAppender(fileAppender);
LoggerConfig root = getRootLogger();
root.setLevel(Level.ALL);
root.addAppender(consoleAppender, Level.ERROR, null);
root.addAppender(fileAppender, Level.INFO, null);
return this;
}
@Override
protected void doConfigure() {}
}.config());
return loggerCtx;
}
@Configuration
static class LoggerConfiguration{
private LoggerContext lctx;
public LoggerContext getLctx() {
return lctx;
}
@Resource
public void setLctx(LoggerContext lctx) {
this.lctx = lctx;
}
@Bean
public Logger commonLogger(){
return lctx.getLogger("com.gxino.webmodel.CommonLogger");
}
}
这段代码的配置较上面有所update,因为想要做一个在控制台只输出Error以上级别的,而保存一个系统日志文件以输出INFO以上级别的日志,所以又做了很多Debug工作。首先一点,Appender不用start(),因为BaseConfiguration.start()时会去做;其次,并不是root.addAppender(appender,appenderLevel,appenderFilter);后,log就能按这个Level去做日志。因为在一个logEvent被响应时,logger会isEnable来判断这个响应奏不奏效,这里面就会根据LoggerConfig即root去判断,然后在logEvent被响应时,才去看每个Appender的具体Level.
而不管是哪里,所有的Level都默认是Level.ERROR,所以我们需要把root的Level调到ALL,让它过了isEnable,再去看具体的Appender的Level.最后,Html的文件日志还是不错嘛。贴个图以结束这一篇内容。
有老手们应该已经发觉,到处充斥着的日志,加起来很繁琐,或说总是忘记去写,有没有方法可以解决?也就是说,在每一个方法的固定位置让它自动写一段日志。那这个固定位置可不可以看成是切面Aspect呢?
OK,下一篇,就引入AOP,面向切面编程。
分享到:
相关推荐
Log4j2学习笔记,引入log4j2的依赖-log4j2.xml配置模板-application.properties文件配置-使用
Java EE Web Application Primer Building Bullhorn A Messaging App with JSP, Servlets, JavaScript, Bootstrap and Oracle 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请...
Build a Twitter-like web application called Bullhorn using Java, Oracle, and more Create web applications using Eclipse Design web pages with HTML forms, tables, and more Use SQL along with Java ...
Digital Java EE 7 Web Application Development 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
用java开发Arcgis server 9.2 web application
Java EE Web Application Primer Building Bullhorn A Messaging App with JSP, Servlets, JavaScript, Bootstrap and Oracle 英文无水印原版pdf pdf所有页面使用FoxitReader、PDF-XChangeViewer、SumatraPDF和...
Prepare for the Pivotal Certified Spring Web Application Developer exam and learn about Spring MVC DispatcherServlet configuration, Spring MVC programming model essentials, Spring MVC views and form ...
Encapsulating security requirements for web development with the Java programming platform, Secure Java: For Web Application Development covers secure programming, risk assessment, and threat ...
信息: Deploying web application directory lx01 2010-11-11 22:52:05 org.apache.catalina.startup.HostConfig deployDirectory 信息: Deploying web application directory blog 2010-11-11 22:52:06 org.apache....
WebApplication1.zip
log4j、ehcache缓存、ApplicationContext配置文件,有需要的小伙伴可以下载
有关JavaApplet和JavaApplication一些介绍
Web压力测试工具 web application stress tool 1.1
Web application struts 2. Web chay tren framework strut.
Apress.Java.EE.Web.Application.Primer.pdf 版本,javaWeb方向入门的书
SpringBoot整合log4jSpringBoot整合log4jSpringBoot整合log4jSpringBoot整合log4j
Web Application Design
Ext.NET Web Application DevelopmentExt.NET Web Application DevelopmentExt.NET Web Application DevelopmentExt.NET Web Application DevelopmentExt.NET Web Application DevelopmentExt.NET Web Application ...