本次实验的项目结构如下:
定义处理日志工具类,在构造函数LogUtil(String logName)中调用org.apache.log4j.Logger的getLogger(logName)方法生成Logger对象。
LogUtil.java
package com.zhuomuniao.myapp.commons.utils;
import java.util.Date;
import org.apache.log4j.Logger;
import com.zhuomuniao.myapp.commons.BusinessException;
/**
* ClassName:LogUtil.java
* Description: 处理日志工具类
**/
public class LogUtil {
private static final String BLANK = " ";
private Logger logger;
public LogUtil(String logName) {
try {
logger = Logger.getLogger(logName);
} catch (Exception e) {
e.printStackTrace();
}
}
public void debug(String para) {
logger.debug(para);
}
public void info(String className, String method, String ip, String userId) {
try {
StringBuffer buf = new StringBuffer();
buf.append("className=[").append(className).append("]").append(BLANK);
buf.append("method=[").append(method).append("]").append(BLANK);
buf.append("ip=[").append(ip).append("]").append(BLANK);
buf.append("userId=[").append(userId).append("]").append(BLANK);
buf.append("opDate=[").append(new Date()).append("]").append(BLANK);
this.logger.info(buf.toString());
} catch (Exception e) {
//todo
}
}
public void infoEx(Throwable para) {
try {
StringBuffer buf = new StringBuffer();
para = getErrorLog(para, buf);
logger.error(buf, para);
} catch (Exception e) {
e.printStackTrace();
}
}
public Throwable getErrorLog(Throwable para, StringBuffer buf) {
try {
BusinessException bisE;
if (para.getClass().getName().endsWith("BusinessException")) {
bisE = (BusinessException) para;
String errorMessage = bisE.getErrorMessage();
buf.append(errorMessage);
para = bisE.getEx();
} else {
buf.append(para.toString());
}
} catch (Exception e) {
e.printStackTrace();
}
return para;
}
}
BaseHttpServlet类继承HttpServlet类,其他所有action都继承此BaseHttpServlet类。
在BaseHttpServlet类中的init方法中创建两个LogUtil对象appLog和errLog,这两个对象分别通过传进去的实参"appLogger"和"errLogger",创建两个org.apache.log4j.Logger对象。
BaseHttpServlet.java
package com.zhuomuniao.myapp.commons;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import com.zhuomuniao.myapp.commons.utils.LogUtil;
/**
* ClassName:BaseHttpServlet.java
* Description: 基础Servlet调用类
*/
public class BaseHttpServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LogUtil appLog;
public LogUtil errLog;
/**
* 系统Servlet启动
*/
public void init(ServletConfig config) throws ServletException {
this.appLog = new LogUtil("appLogger");
this.errLog = new LogUtil("errLogger");
super.init();
}
/**
* 系统Servlet销毁
*/
public void destroy() {
super.destroy();
}
}
log4j的配置文件,此配置文件放在类路径下。
1.本配置文件先对根Logger(即Root)做配置:输出Log信息级别为DEBUG,目的地为 stdout 和 file。 接下来对 stdout 和 file 进行具体的配置。
2.然后本配置文件对上面创建的名为"appLogger"和"errLogger"的两个org.apache.log4j.Logger对象分别配置,
appLogger 输出Log信息级别为DEBUG,目的地为 stdout 和 appFile, 接下来对 appFile 进行具体的配置,stdout 就直接用配置根Logger时使用的。
errLogger 输出Log信息级别为DEBUG,目的地为 stdout 和 errFile, 接下来对 errFile 进行具体的配置,stdout 就直接用配置根Logger时使用的。
log4j.properties文件内容如下:
#设置级别和目的地,级别:'FATAL'、 'ERROR'、'WARN'、'INFO'、'DEBUG'
log4j.rootLogger = DEBUG, stdout, file
#配置输出到控制台的信息格式
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
#输出DEBUG级别以上的日志
log4j.appender.stdout.Threshold=DEBUG
#设置输出样式
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
#自定义样式
log4j.appender.stdout.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}] %5p - %m%n
#直接输出,不进行缓存
log4j.appender.stdout.ImmediateFlush = true
#配置输出到file的文件格式
# org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生新文件)
log4j.appender.file=org.apache.log4j.RollingFileAppender
#设置文件输出路径
log4j.appender.file.File=C:\\logs/Log4JDemo.log
#将消息增加到指定文件中
log4j.appender.file.Append=true
#输出DEBUG级别以上的日志
log4j.appender.file.Threshold=DEBUG
#输出消息编码
log4j.appender.file.encoding=UTF-8
#在日志文件到达该大小时,将会自动滚动,即将原来的内容移到xxx.log.1文件
log4j.appender.file.MaxFileSize=5000KB
#指定可以产生的滚动文件的最大数
log4j.appender.file.MaxBackupIndex=10
#设置输出样式
log4j.appender.file.layout=org.apache.log4j.PatternLayout
#自定义样式
log4j.appender.file.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}] %5p %l - %m%n
#直接输出,不进行缓存
log4j.appender.file.ImmediateFlush = true
log4j.logger.appLogger= DEBUG, stdout, appFile
#用来设置是否同时输出到log4j.rootLogger所配置的日志中,默认为true,这里改为false
log4j.additivity.appLogger = false
log4j.logger.errLogger= DEBUG, stdout, errFile
#用来设置是否同时输出到log4j.rootLogger所配置的日志中,默认为true,这里改为false
log4j.additivity.errLogger = false
#配置输出到appFile的文件格式
# org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生新文件)
log4j.appender.appFile=org.apache.log4j.RollingFileAppender
#设置文件输出路径
log4j.appender.appFile.File=C:\\logs/appFile.log
#将消息增加到指定文件中
log4j.appender.appFile.Append=true
#输出DEBUG级别以上的日志
log4j.appender.appFile.Threshold=DEBUG
#输出消息编码
log4j.appender.appFile.encoding=UTF-8
#在日志文件到达该大小时,将会自动滚动,即将原来的内容移到xxx.log.1文件
log4j.appender.appFile.MaxFileSize=5000KB
#指定可以产生的滚动文件的最大数
log4j.appender.appFile.MaxBackupIndex=10
#设置输出样式
log4j.appender.appFile.layout=org.apache.log4j.PatternLayout
#自定义样式
log4j.appender.appFile.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}] %5p - %m%n
#直接输出,不进行缓存
log4j.appender.appFile.ImmediateFlush = true
#配置输出到errFile的文件格式
# org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生新文件)
log4j.appender.errFile=org.apache.log4j.RollingFileAppender
#设置文件输出路径
log4j.appender.errFile.File=C:\\logs/errFile.log
#将消息增加到指定文件中
log4j.appender.errFile.Append=true
#输出DEBUG级别以上的日志
log4j.appender.errFile.Threshold=DEBUG
#输出消息编码
log4j.appender.errFile.encoding=UTF-8
#在日志文件到达该大小时,将会自动滚动,即将原来的内容移到xxx.log.1文件
log4j.appender.errFile.MaxFileSize=5000KB
#指定可以产生的滚动文件的最大数
log4j.appender.errFile.MaxBackupIndex=10
#设置输出样式
log4j.appender.errFile.layout=org.apache.log4j.PatternLayout
#自定义样式
log4j.appender.errFile.layout.ConversionPattern=[%d{yyyy-MM-dd HH:mm:ss,SSS}] %5p - %m%n
#直接输出,不进行缓存
log4j.appender.errFile.ImmediateFlush = true
数据库连接池
ConnectionPoolManager.java
package com.zhuomuniao.myapp.commons;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* ClassName:ConnectionPoolManager.java
* Description: 连接池
*/
public class ConnectionPoolManager {
private static ConnectionPoolManager instance; // 唯一实例
static synchronized public ConnectionPoolManager getInstance() {
if (instance == null) {
instance = new ConnectionPoolManager();
}
return instance;
}
private ConnectionPoolManager() {
try {
// 装载驱动包类
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
System.out.println("装载数据库驱动包出现异常!");
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException {
Connection conn = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test","s2sh","1234asdf");
} catch (SQLException e) {
System.out.println("链接数据库发生异常!");
e.printStackTrace();
}
return conn;
}
}
自定义异常
BusinessException.java
package com.zhuomuniao.myapp.commons;
/**
* ClassName:BusinessException.java
* Description:自定义异常类
**/
public class BusinessException extends Exception { //继承了Exception这个父类
private static final long serialVersionUID = 1L;
private String methodName;
private String sqlString;
private String sqlErrorCode;
private Exception ex;
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public Exception getEx() {
return ex;
}
public void setSqlString(String sqlString) {
this.sqlString = sqlString;
}
public void setSqlErrorCode(String sqlErrorCode) {
this.sqlErrorCode = sqlErrorCode;
}
public void setEx(Exception ex) {
this.ex = ex;
}
public String getErrorMessage() {
StringBuilder buf = new StringBuilder();
String kaigyo = System.getProperty("line.separator"); //获取系统换行符
if (methodName != null) {
buf.append("Exception happened on ");
buf.append(methodName);
}
if (ex != null) {
buf.append(kaigyo);
buf.append(ex.toString());
}
if (sqlString != null) {
buf.append(kaigyo);
buf.append("SQL = ");
buf.append(sqlString);
}
if (sqlErrorCode != null) {
buf.append(kaigyo);
buf.append("ErrorCode = ");
buf.append(sqlErrorCode);
}
return buf.toString();
}
}
在DAO中,当捕获到SQLException时,生成一个上面的自定义异常类的对象,并调用相应的set方法赋值,随后抛出自定义异常。
StudentDao.java
package com.zhuomuniao.myapp.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import com.zhuomuniao.myapp.commons.BusinessException;
import com.zhuomuniao.myapp.commons.ConnectionPoolManager;
public class StudentDao {
public boolean addStu() throws Exception {
boolean result = true;
Connection conn = null;
PreparedStatement pstmt = null;
StringBuilder sql = new StringBuilder();
sql.append("INSERT INTO TEST (ID, NAME, AGE) ").append("\n");
sql.append("VALUES ( '1','zhuomuniao','27') ");
try {
conn = ConnectionPoolManager.getInstance().getConnection();
conn.setAutoCommit(false);
pstmt = conn.prepareStatement(sql.toString());
pstmt.execute(); //执行数据库更新操作
conn.commit(); //提交事务
} catch (SQLException sqle) {
result = false;
BusinessException bisE = new BusinessException();
bisE.setSqlString(sql.toString());
bisE.setSqlErrorCode(String.valueOf(sqle.getErrorCode()));
bisE.setEx(sqle);
bisE.setMethodName(this.getClass().getName().toString()+" addStu()");
throw bisE;
} finally {
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
if (conn != null) {
conn.close();
conn = null;
}
}
return result;
}
}
StudentService.java
package com.zhuomuniao.myapp.service;
import com.zhuomuniao.myapp.dao.StudentDao;
public class StudentService {
private StudentDao studentDao=new StudentDao();
public void addStu() throws Exception {
studentDao.addStu();
}
}
在action中捕获到DAO中抛出的自定义异常后,通过调用此类的父类BaseHttpServlet中定义的处理日志工具类LogUtil对象errLog的infoEx方法记录到日志中。
当然,如果DAO正常执行,没有异常,则在action中调用此类的父类BaseHttpServlet中定义的处理日志工具类LogUtil对象appLog的info方法记录到日志中。
StudentAction.java
package com.zhuomuniao.myapp.action;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.zhuomuniao.myapp.commons.BaseHttpServlet;
import com.zhuomuniao.myapp.commons.BusinessException;
import com.zhuomuniao.myapp.service.StudentService;
@SuppressWarnings("serial")
public class StudentAction extends BaseHttpServlet {
private StudentService studentService = new StudentService ();
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String action = request.getParameter("action");
if("addStu".equals(action))
doAddStu(request, response);
}
public void doAddStu(HttpServletRequest request, HttpServletResponse response){
try {
studentService.addStu();
super.appLog.info(
this.getClass().getName(),
"doAddStu(HttpServletRequest request, HttpServletResponse response)",
request.getRemoteAddr(),
"userId");
} catch (BusinessException be) {
super.errLog.infoEx(be);
} catch (Exception e) {
super.errLog.infoEx(e);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(req, resp);
}
}
实验结果截图:
1. 利用log4j输出用户自定义异常信息到控制台。
2. 利用log4j输出用户自定义异常信息到日志文件errFile.log。
3. 利用log4j输出信息到控制台。
4. 利用log4j输出信息到日志文件appFile.log。
log4j产生的日志文件目录
下载地址: http://download.youkuaiyun.com/detail/chuzhenbin/4159298
==============以上================