分享

log4j 实现日志存入数据库

 昵称33192209 2016-05-10
o
增加配置:

<!-- 将log保存到DB -->
<appender name="db_info" class="com.mufare.tools.JDBCAppender">
   <param name="BufferSize" value="1" />  
   <param name="URL" value="jdbc:oracle:thin:@10.221.23.40:1521:MUFARE" />
   <param name="Driver" value="oracle.jdbc.OracleDriver" />
   <param name="user" value="MUATPCO" />
   <param name="password" value="admin" />
   <param name="sql" value="INSERT INTO T_LOG(currtime,currthread,currlevel,currcode,currmsg) VALUES (?, ?, ?, ?, ?)" />  
</appender> 

<category name = "accesslog_category"> 
 <priority value = "debug"/> 
 <appender-ref ref = "db_info"/> 
 <appender-ref ref="CONSOLE" />  
</category>
<!-- 将log保存到DB -->


增加java类:
public class AccessLogFactory {
 private static final String ACCESSLOG_CATEGORY = "accesslog_category";
 static {
  DOMConfigurator.configure("./resource/log4j.xml");
 }
 public static Log getLog() {
  Log logger = null;
  try {
   logger = LogFactory.getLog(ACCESSLOG_CATEGORY);
  } catch (LogConfigurationException e) {
   e.printStackTrace();
  }
  return logger;
 }
}

增加java类:
public class JDBCAppender extends org.apache.log4j.AppenderSkeleton {
 /**
  * URL of the DB for default connection handling
  */
 protected String databaseURL = "jdbc:odbc:myDB";
 /**
  * User to connect as for default connection handling
  */
 protected String databaseUser = "me";
 /**
  * User to use for default connection handling
  */
 protected String databasePassword = "mypassword";
 /**
  * Connection used by default. The connection is opened the first time it is
  * needed and then held open until the appender is closed (usually at
  * garbage collection). This behavior is best modified by creating a
  * sub-class and overriding the <code>getConnection</code> and
  * <code>closeConnection</code> methods.
  */
 protected Connection connection = null;
 /**
  * Stores the string given to the pattern layout for conversion into a SQL
  * statement, eg: insert into LogTable (Thread, Class, Message) values
  * ("%t", "%c", "%m").
  *
  * Be careful of quotes in your messages!
  *
  * Also see PatternLayout.
  */
 protected String sqlStatement = "";
 /**
  * size of LoggingEvent buffer before writting to the database. Default is
  * 1.
  */
 protected int bufferSize = 1;
 /**
  * ArrayList holding the buffer of Logging Events.
  */
 protected ArrayList buffer;
 /**
  * Helper object for clearing out the buffer
  */
 protected ArrayList removes;
 private boolean locationInfo = false;
 public JDBCAppender() {
  super();
  buffer = new ArrayList(bufferSize);
  removes = new ArrayList(bufferSize);
 }
 /**
  * Gets whether the location of the logging request call should be captured.
  *
  * @since 1.2.16
  * @return the current value of the <b>LocationInfo</b> option.
  */
 public boolean getLocationInfo() {
  return locationInfo;
 }
 /**
  * The <b>LocationInfo</b> option takes a boolean value. By default, it is
  * set to false which means there will be no effort to extract the location
  * information related to the event. As a result, the event that will be
  * ultimately logged will likely to contain the wrong location information
  * (if present in the log format).
  * <p/>
  * <p/>
  * Location information extraction is comparatively very slow and should be
  * avoided unless performance is not a concern.
  * </p>
  *
  * @since 1.2.16
  * @param flag
  *            true if location information should be extracted.
  */
 public void setLocationInfo(final boolean flag) {
  locationInfo = flag;
 }
 /**
  * Adds the event to the buffer. When full the buffer is flushed.
  */
 public void append(LoggingEvent event) {
  event.getNDC();
  event.getThreadName();
  // Get a copy of this thread's MDC.
  event.getMDCCopy();
  if (locationInfo) {
   event.getLocationInformation();
  }
  event.getRenderedMessage();
  event.getThrowableStrRep();
  buffer.add(event);
  if (buffer.size() >= bufferSize) {
   flushBuffer();
  }
 }
 /**
  * By default getLogStatement sends the event to the required Layout object.
  * The layout will format the given pattern into a workable SQL string.
  *
  * Overriding this provides direct access to the LoggingEvent when
  * constructing the logging statement.
  *
  */
 protected String getLogStatement(LoggingEvent event) {
  return getLayout().format(event);
 }
 /**
  *
  * Override this to provide an alertnate method of getting connections (such
  * as caching). One method to fix this is to open connections at the start
  * of flushBuffer() and close them at the end. I use a connection pool
  * outside of JDBCAppender which is accessed in an override of this method.
  */
 protected void execute(String sql) throws SQLException {
  Connection con = null;
  Statement stmt = null;
  try {
   con = getConnection();
   stmt = con.createStatement();
   stmt.executeUpdate(sql);
  } finally {
   if (stmt != null) {
    stmt.close();
   }
   closeConnection(con);
  }
  // System.out.println("Execute: " + sql);
 }
 /**
  * Override this to return the connection to a pool, or to clean up the
  * resource.
  *
  * The default behavior holds a single connection open until the appender is
  * closed (typically when garbage collected).
  */
 protected void closeConnection(Connection con) {
 }
 /**
  * Override this to link with your connection pooling system.
  *
  * By default this creates a single connection which is held open until the
  * object is garbage collected.
  */
 protected Connection getConnection() throws SQLException {
  if (!DriverManager.getDrivers().hasMoreElements()) {
   setDriver("sun.jdbc.odbc.JdbcOdbcDriver");
  }
  if (connection == null) {
   connection = DriverManager.getConnection(databaseURL, databaseUser, databasePassword);
  }
  return connection;
 }
 /**
  * Closes the appender, flushing the buffer first then closing the default
  * connection if it is open.
  */
 public void close() {
  flushBuffer();
  try {
   if (connection != null && !connection.isClosed()) {
    connection.close();
   }
  } catch (SQLException e) {
   errorHandler.error("Error closing connection", e, ErrorCode.GENERIC_FAILURE);
  }
  this.closed = true;
 }
 /**
  * loops through the buffer of LoggingEvents, gets a sql string from
  * getLogStatement() and sends it to execute(). Errors are sent to the
  * errorHandler.
  *
  * If a statement fails the LoggingEvent stays in the buffer!
  */
 public void flushBuffer() {
  // Do the actual logging
  removes.ensureCapacity(buffer.size());
  for (Iterator i = buffer.iterator(); i.hasNext();) {
   LoggingEvent logEvent = (LoggingEvent) i.next();
   try {
    Connection con = getConnection();
    PreparedStatement stmt = con.prepareStatement(getSql());
    stmt.setString(1, DateUtil.formatCurDate().concat(DateUtil.formatCurTime()));
    stmt.setString(2, logEvent.getThreadName());
    stmt.setString(3, logEvent.getLevel().toString());
    stmt.setString(4, logEvent.getLoggerName());
    stmt.setString(5, logEvent.getMessage().toString());
    stmt.executeUpdate();
   } catch (SQLException e) {
    errorHandler.error("Failed to excute sql", e, ErrorCode.FLUSH_FAILURE);
   } finally {
    removes.add(logEvent);
   }
  }
  // remove from the buffer any events that were reported
  buffer.removeAll(removes);
  // clear the buffer of reported events
  removes.clear();
 }
 /** closes the appender before disposal */
 public void finalize() {
  close();
 }
 /**
  * JDBCAppender requires a layout.
  */
 public boolean requiresLayout() {
  return true;
 }
 /**
  *
  */
 public void setSql(String sql) {
  sqlStatement = sql;
  if (getLayout() == null) {
   this.setLayout(new PatternLayout(sql));
  } else {
   ((PatternLayout) getLayout()).setConversionPattern(sql);
  }
 }
 /**
  * Returns pre-formated statement eg: insert into LogTable (msg) values
  * ("%m")
  */
 public String getSql() {
  return sqlStatement;
 }
 public void setUser(String user) {
  databaseUser = user;
 }
 public void setURL(String url) {
  databaseURL = url;
 }
 public void setPassword(String password) {
  databasePassword = password;
 }
 public void setBufferSize(int newBufferSize) {
  bufferSize = newBufferSize;
  buffer.ensureCapacity(bufferSize);
  removes.ensureCapacity(bufferSize);
 }
 public String getUser() {
  return databaseUser;
 }
 public String getURL() {
  return databaseURL;
 }
 public String getPassword() {
  return databasePassword;
 }
 public int getBufferSize() {
  return bufferSize;
 }
 /**
  * Ensures that the given driver class has been loaded for sql connection
  * creation.
  */
 public void setDriver(String driverClass) {
  try {
   Class.forName(driverClass);
  } catch (Exception e) {
   errorHandler.error("Failed to load driver", e, ErrorCode.GENERIC_FAILURE);
  }
 }
}

 
增加表:
create table T_LOG
(
  currtime   VARCHAR2(20) not null,
  currthread CHAR(100),
  currlevel  CHAR(10),
  currcode   CHAR(20),
  currmsg    CHAR(200)
)
调用:
Log logger = AccessLogFactory.getLog();
logger.debug("XXXX")
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多