JavaWeb15日志及异常处理.docx
- 文档编号:26879347
- 上传时间:2023-06-23
- 格式:DOCX
- 页数:22
- 大小:420.88KB
JavaWeb15日志及异常处理.docx
《JavaWeb15日志及异常处理.docx》由会员分享,可在线阅读,更多相关《JavaWeb15日志及异常处理.docx(22页珍藏版)》请在冰豆网上搜索。
JavaWeb15日志及异常处理
第5章日志及异常处理
我们学习过Java异常处理和JSP的相关课程。
本章,我们将对Web应用程序中得异常集中处理。
对于情况严重的系统异常我们需要将其写入日志文件,对于用于操作不规范的异常我们应该给出客户友好的提示信息。
在本章中我们将讲解如何使用lor4j框架来实现日志文件的记录,以及如何设计web应用程序的结构来实现相应异常的处理。
5.1日志概述
5.1.1日志简介
软件的运行过程离不开日志。
日志的主要作用是记录一些重要的操作信息,比如应用权限的修改、程序运行的系统异常、导致致命错误的异常,日志文件记录的信息一般包括错误类型、时间、错误点。
日志文件能够帮助用户提前发现和避免灾难,并且找到系统发生的根本原因。
位程序的升级、维护提供有力保障。
比如当你开发完一个项目、并交互给客户使用后发现在客户的环境中不能运行。
由于是以window服务的防是启动的web服务器,所有不能使用控制台的方式查看异常信息,这时将给维护人员或实施人员将无从下手。
但如果将系统的异常信息记录到日志文件中,维护人员或实施人员就可以根据日志文件中记录的运行信息解决问题。
也就是说在我们开发的系统中需要将运行的一些信息、状态、过程使用文件流的方式将其写在硬盘的某一个文件或多个文件中,这就是我们所说的日志记录。
5.1.2log4j简介
log4j是Apache的一个开放源代码项目,log4j框架是用Java语言编写的标准日志记录框架。
作为Jakarta项目的一部分,它在Apache软件许可证(ApacheSoftwareLicense)下分发,以速度和灵活性为中心概念:
log4j环境是完全可配置的,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。
最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。
此外,通过Log4j其他语言接口,您可以在C、C++、.Net、PL/SQL程序中使用Log4j,其语法和用法与在Java程序中一样,使得多语言分布式系统得到一个统一一致的日志组件模块。
而且,通过使用各种第三方扩展,您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。
log4j的好处在于:
通过修改配置文件,就可以决定log信息的目的地——控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等。
通过修改配置文件,可以定义每一条日志信息的级别,从而控制是否输出。
在系统开发阶段可以打印详细的log信息以跟踪系统运行情况,而在系统稳定后可以关闭log输出,从而在能跟踪系统运行情况的同时,又减少了垃圾代码(System.out.println(......)等)。
使用log4j,需要整个系统有一个统一的log机制,有利于系统的规划。
5.2log4j的使用
log4j是apache提供的开源的第三方框剪,也就是在在j2ee开发包中并没有对log4j的支持,当我们需要使用log4j时必须添加相应的jar包。
根据前面对于log4j的介绍我们知道它是通过配置文件来设置输入的内容、格式、目标,所以我们也必须掌握log4j配置文件的编写。
最后还需在代码中添加log4j的调用。
由此可知log4j日志系统的使用步骤有:
添加log4j支持、配置log4j配置文件、在java代码中调用log4j记录日志。
5.2.1添加log4j
首先需要获取log4j的jar包,可以在apache的官方网站中下载、其下载页面路径是http:
//logging.apache.org/,该页面中包含log4j的所有版本下载,如:
1.2、1.3、2.0。
下载后将其保存在指定目录中。
然后就可以将log4j的jar包添加到web应用程序中。
选择web应用程序项目点击右键【Properties】【JavaBuildPath】出现如图5-1所示的界面。
图5-1添加jar包
选择【Libraries】【AddExternalJARs】出现如图5-2所示的文件选择对话框。
图5-2选择log4j支持包
选择log4j支持包完成添加。
5.2.2创建log4j配置文件
log4j配置文件必须保存在源代码跟目录中、及src下,并且文件名是log4j.properties(也可以使用log4j.xml文件配置)。
选择src目录点击右键,选择【New】【File】选项,弹出“新建文件”对话框,输入文件名“log4j.properties”,点击“完成”按钮,创建工作结束,如图5-3所示。
图5-3创建配置文件
src中的log4j.properties配置文件是专门用来配置日志信息的输出内容、格式等。
该配置文件的内容如下:
##配置到控制台的日志信息输出源##
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d%m%n
##配置到文件的日志信息输出源##
log4j.appender.f=org.apache.log4j.FileAppender
log4j.appender.f.File=i:
/test.log
log4j.appender.f.layout=org.apache.log4j.PatternLayout
log4j.appender.f.layout.ConversionPattern=%d{yyyy-MM-ddHH:
mm:
ss}%l%m%n
##设置日志信息的输出级别和启动的输出源##
log4j.rootLogger=warn,stdout
MyEclipse中属性文件默认的编码格式为ISO-8859-1,该编码不支持中文。
当属性文件中包含中文内容时将无法保存,此时可以修改文件的编码格式,选择菜单【Window】【Preferences】【Genernal】【ContentTypes】出现如图5-4所示的文档格式设置界面。
图5-4修改编码格式
选择图5-4中的ContentTypes中的【Text】【JavaPropertiesFile】,修改Defaultencoding的值为“UTF-8”,即将属性文件的默认编码格式修改为“UTF-8”字符集。
如图5-5所示。
图5-5修改编码格式
点击【Update】【OK】完成编码格式修改。
在log4j.properties文件中所配置的内容包含如下几点:
1、输出源配置
输出源配置是指将日志信息以指定格式输出到指定的目标,一般目标分为两种、即控制台和文件。
如果输出目标类是时控制台则使用org.apache.log4j.ConsoleAppder类实现输出管理、目标属性为System.out(系统标准输出流);如果输出目标是日志文件则使用org.apache.log4j.FileAppender类实现输出管理、目标属性File登录日志文件路径和文件名。
当然日志文件输出目标除了控制台、文件外还有HTML页面等形式。
2、输出源布局配置
输出源都需要使用org.apache.log4j.PatternLayout类实现输出日志内容格式和布局管理,在配置文件中通过log4j.appender.f.layout.ConversionPattern配置PatternLayout类的日志信息格式。
%d表示在日志信息中出当前系统时间、时间的格式通过后面的一个日期格式的字符串表达式控制(字符串表达式的格式和SimpleDateFormat)相同;%l表示在日志信息中输出事件发生的文字,包括雷鸣、发生的线程、以及代码中的行数。
例如:
输出日志信息为:
com.sanlian.javaWeb.ch5.Test.main(Test.java:
16)
说明日志事件发生在Test类中的main线程中,在代码中的行数为第16行;%p表示输出日志信息的级别;%m用来输出调用log4j代码中的指定信息;%n用于输出一个回车换行符。
3、优先级配置
在log4j中的日志信息是有优先级别的,通过log4j.rootLogger配置。
在log4j中的优先级有:
off、fatal、error、warn、info、debug、all或者您定义的级别。
log4j建议只使用四个级别,优先级从高到低分别是error、warn、info、debug。
通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。
假如在一个级别为q的Logger中发生一个级别为p的日志请求,如果p>=q,那么请求将被启用。
比如在配置文件定义的输出级别是info,则应用程序中所有debug级别的日志信息将不被打印出来。
因为debug的优先级别小于info,所以不会输出。
4、启动输出源
在配置文件中配置的输出目标不会都起作用,只是使用到的输出源才会起效,这需要在配置优先级的log4j.rootLogger后添加相应的输出源,如配置文件中的:
log4j.rootLogger=warn,stdout
表示在设置输出级别为warn的同时启动stdout输出源,及日志信息将会输出到控制台,但是不会输出到e盘的test.log文件中。
当然在配置文件中也可以启动多个输出源,如:
log4j.rootLogger=warn,stdout,f
表示将日志信息同时输出在控制台和e:
/test.log文件中。
5、注释
在属性文件中(即后缀名为.properties的文件)使用“#”编写注释。
5.2.3使用log4j输出日志
当完成支持添加和配置文件添加之后就可以在程序中使用log4j了。
在例5-1中我们通过测试类来实现不同级别的日志信息输出。
例5-1:
记录日志信息
packagecom.sanlian.javaWebAd.ch5;
importorg.apache.log4j.Logger;
publicclassTest{
publicstaticvoidmain(String[]args){
//获得日志记录器,这个记录器将负责控制日志信息
Loggerlog=Logger.getLogger(Test.class);
//调用log对象的相应方法输出不同级别的日志信息
//输出fatal级别的日志信息
log.fatal("----fatal----");
//输出error级别的日志信息
log.error("----error----");
//输出warn级别的日志信息
log.warn("----warn-----");
//输出info级别的日志信息
log.info("----info-----");
//输出debug级别的日志信息
log.info("----debug----");
}
}
在上例中,我们使用日志记录器的相应方法输出了每种级别的日志信息。
其输出内容如图5-6所示。
图5-6log4j输出结果
因为在配置文件中设置了输出级别为warn,所以比warn级别低的info、debug信息没有被输出。
又因为没有在配置文件中启动文件输出源,所示在i盘中不能找到test.log文件和日志信息。
如果修改配置文件的级别和输出源如下:
log4j.rootLogger=debug,stdout,f
运行时将看到空台的内容如图5-7所示。
图5-7输出所有级别的日志信息
在i盘中生成的test.log内容如图5-8所示。
图5-8日志文件
对比5-7和5-8我们可以看出在日志文件中记录的每个日志信息所发生的位置,这是因为我们在文件输出源的布局方式中使用%l的缘故。
5.3web应用程序架构设计
在web应用程序中有很多的异常,如果不进行相应的处理在页面将不能得到友好的提示信息,并且也不能为维护人员提供技术保障。
在web应用程序中的异常通常分为两种类型,即系统异常及业务异常。
系统异常通常需要记录到日志文件中,方便维护人员解决问题;业务异常需要返回给客户端作出友好的提示。
结合MVC设计模式和log4j日志系统可以对系统进行如图5-9所示的架构,以便将系统异常记录日志、将业务异常提示给客户端。
图5-9web应用程序架构图
图5-9中的黑色实体线条表示请求走向和模块调用走向。
当请求进入web应用程序是首先都必须经过BaseServlet,然后才是执行相应的控制处理servlet,通过servlet调用业务方法,业务方法调用DAO访问数据库。
图5-9中的红色虚线表示异常处理的流程。
在程序中异常可能会在每一个阶段发生,但是所有的异常都向外抛出,一直抛到BaseServlet集中处理。
为了能够在BaseServlet中方便集中处理异常,我们在程序中创建两个自定义异常类,分别是BizException、SysException。
其实现代码如下:
BizSysException类
packagecom.sanlian.javaWebAd.ch5.util;
/**
*自定义业务异常
*/
publicclassBizExceptionextendsRuntimeException{
publicBizException(Stringmessage){
super(message);
}
}
SysException类
packagecom.sanlian.javaWebAd.ch5.util;
/**
*自定义系统异常
*/
publicclassSysExceptionextendsRuntimeException{
publicSysException(Stringmessage){
super(message);
}
}
BizException、SysException通过继承RuntimeException可以降低代码中异常手动抛出的痛苦,因为运行时异常不需要在方法中使用try…catch处理、也不需要在方法手使用throws显示的声明。
在BaseServlet中通过判断异常的类型来实现不同的处理,其实现代码如下:
BaseServlet类
packagecom.sanlian.javaWebAd.ch5.web.servlet;
importjava.io.IOException;
importjavax.servlet.ServletException;
importjavax.servlet.http.HttpServlet;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importorg.apache.log4j.Logger;
importcom.sanlian.javaWebAd.ch5.util.BizException;
publicclassBaseServletextendsHttpServlet{
@Override
protectedvoidservice(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{
try{
super.service(request,response);
}
catch(Exceptione){
//判断异常的内容
if(einstanceofBizException){
//自定义异常,将异常信息保存到request中
request.setAttribute("errorMessage",e.getMessage());
}
else{
Stringmessage="系统正在升级维护,请于管理员联系!
";
request.setAttribute("errorMessage",message);
//记录日志log4j
Loggerlog=Logger.getLogger(BaseServlet.class);
log.warn(e.getMessage());
}
//跳转到错误页面
Stringurl="/common/error.jsp";
request.getRequestDispatcher(url).forward(request,response);
}
}
}
在该BaseServlet中通过判断异常类型进行操作。
如果是业务类型则直接将业务信息保存在request中,并跳转错误页面显示业务信息;如果是系统异常则将异常信息记录到日志文件中,并保存一个友好的提示信息在request中,并跳转到错误页面提示。
普通的控制Servlet通过继承至BaseServlet来实现异常的总处理。
错误页面的实现代码如下所示:
error.jsp
<%@pagelanguage="java"pageEncoding="UTF-8"%>
${requestScope.errorMessage}
如例5-2通过该架构完成用户登录操作。
例5-2:
用户登录
通过如上的系统架构可知登录功能的流程如图5-10所示。
图5-10登录流程图
数据库名为DB,其中有一表个内容如下:
createtableuser_info(
user_idintidentity(1,1)primarykey,
user_novarchar(15)notnull,
user_accountvarchar(30)notnull,
user_passvarchar(30)notnull,
user_namevarchar(20)notnull,
user_pidvarchar(18)notnull,
user_sexbitdefault
(1)notnull,
user_birthdaydatetimenotnull,
user_addressvarchar(100)null,
user_emailvarchar(50)null
)
创建和表相对应的实体类UserInfo。
1、DataUtil类
DataUtil用于创建数据库连接对象和关闭数据库连接对象,实现代码如下:
packagecom.sanlian.javaWebAd.ch5.pers;
importjava.sql.Statement;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.ResultSet;
importjava.sql.SQLException;
/**
*数据功能类
*得到数据库连接、关闭数据库连接
*/
publicclassDataUtil{
/**
*得到数据库连接对象
*/
publicstaticConnectiongetConn()throwsException{
Connectionconn=null;
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Stringurl="jdbc:
sqlserver:
//localhost:
1433;databaseName=DB";
conn=DriverManager.getConnection(url,"sa","123456");
returnconn;
}
/**
*关闭查询
*@paramrs结果集
*@paramst上下文
*@paramconn连接
*/
publicstaticvoidcloseConn(ResultSetrs,Statementst,Connectionconn){
try{
rs.close();
}
catch(Exceptione){}
try{
st.close();
}
catch(Exceptione){}
try{
conn.close();
}
catch(Exceptione){}
}
/**
*关闭增、删、该
*@paramst上下文
*@paramconn连接
*/
publicstaticvoidcloseConn(Statementst,Connectionconn){
try{
st.close();
}
catch(Exceptione){}
try{
conn.close();
}
catch(Exceptione){}
}
}
2、UserDAO类
该类称为数据访问类。
在web应用程序中将所有的数据访问类统称为数据访问层,主要用于对数据的数据进行访问,执行增、删、改、查sql语句。
UserDAO类的实现代码如下所示:
packagecom.sanlian.javaWebAd.ch5.pers.dao;
importjava.sql.Connection;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importcom.sanlian.javaWebAd.ch5.entity.UserInfo;
importcom.sanlian.javaWebAd.ch5.pers.DataUtil;
importcom.sanlian.javaWebAd.ch5.util.SysException;
publicclassUserDAO{
publicUserInfoqueryByAccount(Stringaccount){
UserInfouser=null;
//定义数据库访问对象
Connection
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- JavaWeb15 日志 异常 处理