在上面提及异常的中英文从资源文件中读取,若读取失败需要日志记录,所以使用网上正在闹腾的Logback来记录。关于Logback与Log4j这里不做评判和说明,所有疑问可以请教谷歌。
一、Logback的使用前期准备
1、在官网http://logback.qos.ch/download.html下载Logback;在官网http://www.slf4j.org/download.html下载slf4j
2、在D:\medical\war\WEB-INF下创建lib文件夹,用于放置本应用的所需JAR包
3、解压上面的下载,把logback-access-1.0.13.jar、logback-classic-1.0.13.jar、logback-core-1.0.13.jar和slf4j-api-1.7.5.jar复制到D:\medical\war\WEB-INF\lib中
二、测试类
下面着手写一个与本应用无关的测试类FrameLogger.java
1、打开Eclipse,在medical工程上右键,选择“New > Class”,Package填写“com.medical.frame”,Name填写“FrameLoggerDemo”,点击“Finish”
2、要使用日志类,应用先定义一个Logger,然后再使用这个对象,所以代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
package
com.medical.frame;
import
org.slf4j.Logger;
import
org.slf4j.LoggerFactory;
public
class
FrameLoggerDemo
{
private
static
final
Logger logger = LoggerFactory.getLogger(FrameLoggerDemo.
class
);
public
static
void
main(String[] args)
{
logger.info(
"It's test for logback."
);
}
}
|
3、你会发现上面代码编译不通过。这很正常,因为Eclipse没有导入所需的jar包。右键medical工程选择“Properties > Java Build Path > Libraries > Add JARs...”,在JAR选择窗口中把D:\medical\war\WEB-INF\lib下的jar包添加进来,如图:
4、我想不仅把日志打印到控制台还要打印到日志文件中,更甚者想插入到数据库中,XML配置文件可以协助完成。在D:\medical\war\下创建etc文件夹,然后在etc下创建logconfig.xml文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<?
xml
version
=
"1.0"
encoding
=
"UTF-8"
?>
<
configuration
>
<!--日志文件的存储地址,一定要使用绝对路径-->
<
property
name
=
"LOG_HOME"
value
=
"D:/log"
/>
<!--日志文件后缀格式-->
<
timestamp
key
=
"fileSuffix"
datePattern
=
"yyyyMMdd'_'HHmm"
/>
<!--控制台输出-->
<
appender
name
=
"STDOUT"
class
=
"ch.qos.logback.core.ConsoleAppender"
>
<!--输出在控制台上的日志字符串编码-->
<
Encoding
>UTF-8</
Encoding
>
<!--输出在控制台上的日志格式-->
<
layout
class
=
"ch.qos.logback.classic.PatternLayout"
>
<!--%d表示日期; %thread表示线程名; %-5level表示从左显示5个字符宽度的级别名; %logger表示日志类; %msg表示日志消息; %n表示换行-->
<
pattern
>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{60} - %msg%n</
pattern
>
</
layout
>
</
appender
>
<!--文件输出-->
<
appender
name
=
"FILE"
class
=
"ch.qos.logback.core.rolling.RollingFileAppender"
>
<!--输出在控制台上的日志字符串编码-->
<
Encoding
>UTF-8</
Encoding
>
<!--日志对应的文件名-->
<
file
>${LOG_HOME}/trace${fileSuffix}.txt</
file
>
<!--日志文件记录滚动策略-->
<
rollingPolicy
class
=
"ch.qos.logback.core.rolling.FixedWindowRollingPolicy"
>
<!--当日志文件超过大小时就压缩为zip包-->
<
fileNamePattern
>${LOG_HOME}/trace${fileSuffix}.%i.zip</
fileNamePattern
>
<!--最多有10个zip压缩包,超过10就覆盖之前的-->
<
minIndex
>1</
minIndex
>
<
maxIndex
>10</
maxIndex
>
</
rollingPolicy
>
<!--文件超过5M就重新生成新的日志文件,老的日志文件压缩成zip包-->
<
triggeringPolicy
class
=
"ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"
>
<
maxFileSize
>5MB</
maxFileSize
>
</
triggeringPolicy
>
<!--输出在文件上的日志格式-->
<
encoder
>
<
pattern
>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{60} - %msg%n </
pattern
>
</
encoder
>
</
appender
>
<!--日志输出级别-->
<
root
level
=
"INFO"
>
<
appender-ref
ref
=
"STDOUT"
/>
<
appender-ref
ref
=
"FILE"
/>
</
root
>
</
configuration
>
|
【备注】:关于这个配置文件建议感兴趣的读者,自己亲自配置一下,这样才能体验每个标签的含义。
5、运行FrameLoggerDemo发现并没有在指定的D:/log下输出日志文件。试想一下,我们都没有告诉Logback输出策略是什么,它怎么又会知道呢?所以这里需要在main()运行之前把logconfig.xml加载进来,怎么加载?怎么只加载一次?方法很多,可以使用Spring的单例工厂,而这里我们使用单例类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
private
static
FrameLoggerDemo instance =
new
FrameLoggerDemo();
private
FrameLoggerDemo()
{
String logbackCfg =
"D:\\medical\\war\\etc\\logconfig.xml"
;
ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
JoranConfigurator configurator =
new
JoranConfigurator();
configurator.setContext((LoggerContext) loggerFactory);
try
{
configurator.doConfigure(logbackCfg);
}
catch
(JoranException e)
{
e.printStackTrace();
}
}
|
三、斗医应用如何使用Logback呢?
从上面的FrameLoggerDemo可以看到,系统在使用Logger对象之前必须把配置文件加载进来,对于web应用它由多个Servlet构成,所以最好在第一个Servlet启动时加载进来,后续的使用者就直接使用即可。
1、在D:\medical\war\WEB-INF\web.xml中定义名称为action的servlet
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<
web-app
>
<
servlet
>
<
servlet-name
>action</
servlet-name
>
<
servlet-class
>com.medical.frame.FrameLauncher</
servlet-class
>
<
load-on-startup
>1</
load-on-startup
>
</
servlet
>
<
servlet-mapping
>
<
servlet-name
>action</
servlet-name
>
<
url-pattern
>*.act</
url-pattern
>
</
servlet-mapping
>
<
welcome-file-list
>
<
welcome-file
>index.html</
welcome-file
>
</
welcome-file-list
>
</
web-app
>
|
2、该servlet说明当客户端的请求为*.act时,都使用名称为action的servlet处理,处理器为FrameLauncher这个类,它必须继承HttpServlet。Servlet一般由init、doGet、doPost、destory方法构成,所以FrameLauncher也不例外,它需要重写这4个方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package
com.medical.frame;
import
javax.servlet.ServletException;
import
javax.servlet.http.HttpServlet;
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
/**
* 斗医系统动作登陆类
*/
public
class
FrameLauncher
extends
HttpServlet
{
@Override
public
void
init()
throws
ServletException
{
}
@Override
public
void
doGet(HttpServletRequest request, HttpServletResponse response)
throws
ServletException
{
}
@Override
public
void
doPost(HttpServletRequest request, HttpServletResponse response)
throws
ServletException
{
doGet(request, response);
}
@Override
public
void
destroy()
{
}
}
|
3、当request请求到达Web容器时,它会根据请求参数判断使用哪个servlet处理,当servlet首次被调用到时,它会反射<servlet-class>定义的类,再调用init()方法进行初始化。而我们的日志加载就可以在这里处理。
定义com.medical.frame.util.FrameConfigUtil.java,里面定义静态方法initLogConfig()用于加载logback日志配置文件。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public
class
FrameConfigUtil
{
/**
* 加载Logback日志配置文件
*/
public
static
void
initLogConfig(ServletContext context)
{
// 获取logback配置文件
StringBuilder logConfigPath =
new
StringBuilder(context.getRealPath(
"/"
));
logConfigPath.append(
"etc"
).append(File.separator).append(
"logconfig.xml"
);
// 加载logback配置文件
ILoggerFactory loggerFactory = LoggerFactory.getILoggerFactory();
JoranConfigurator configurator =
new
JoranConfigurator();
configurator.setContext((LoggerContext) loggerFactory);
try
{
configurator.doConfigure(logConfigPath.toString());
}
catch
(JoranException e)
{
System.out.println(
"[重要] init logback config error.\n"
+ e.getMessage());
}
}
}
|
4、FrameLauncher.init()方法调用FrameConfigUtil.initLogConfig()
1
2
3
4
5
6
|
@Override
public
void
init()
throws
ServletException
{
ServletContext context = getServletContext();
FrameConfigUtil.initLogConfig(context);
}
|
至此logback的配置文件在action这个servlet初始化时就加载完了,那该如何测试呢?
5、修改D:\medical\war\index.html文件内容,修改后的内容如下:
1
2
3
4
5
6
7
8
|
<
html
>
<
head
>
<
title
>medical</
title
>
</
head
>
<
body
>
<
a
href
=
"index.act"
>Test Logback</
a
>
</
body
>
</
html
>
|
6、重写com.medical.frame.FrameLauncher.doGet()方法
1
2
3
4
5
6
7
8
9
|
/**
* 定义日志对象
*/
private
static
final
Logger logger = LoggerFactory.getLogger(FrameLauncher.
class
);
@Override
public
void
doGet(HttpServletRequest request, HttpServletResponse response)
throws
ServletException
{
logger.error(
"It's test for logback."
);
}
|
这样当在浏览器中输入http://localhost:8080/medical时,由web.xml的<welcome-file-list>定义知系统首先加载index.html文件,当用鼠标点击Test Logback会index.act的HTTP请求发送给Tomcat容器,Tomcat根据web.xml的<url-pattern>*.act</url-pattern>找到对应的<servlet-name>action</servlet-name>,然后反射加载com.medical.frame.FrameLauncher.java,当FrameLaucher加载时调用init()方法把logconfig.xml读入,接着把HTT请求转换为HttpServletReqeust请求交给doGet(),从而把日志打印出来。
【备注1】:若用户从头到尾地写这个应用,有可能会发现,尽管在D:\log下生成了日志文件,但里面没有内容,这有可能是在加载logconfig.xml时使用的JoranConfigurator不正确。应该使用import ch.qos.logback.classic.joran.JoranConfigurator,而非import ch.qos.logback.access.joran.JoranConfigurator。
【备注2】:若在实际操作这个实例时遇到问题,可参见附件,也可评论以便及时交流
附件:http://down.51cto.com/data/2363607
本文转自qingkechina 51CTO博客,原文链接:http://blog.51cto.com/qingkechina/1308932,如需转载请自行联系原作者