項目重構之數據源配置與優化:log4j 配置數據庫連接池Druid,並實現日志存儲到數據庫


作者:泥沙磚瓦漿木匠
網站
http://blog.csdn.net/jeffli1993
個人簽名打算起手不凡寫出鴻篇巨作的人,往往堅持不了完成第一章節。

交流QQ群:【編程之美 365234583】http://qm.qq.com/cgi-bin/qm/qr?k=FhFAoaWwjP29_AonqzL0rpdQAjjqlHQQ

如果我的幫到了你,是否樂意捐助一下或請一杯啤酒也好呢?有你支持,干的更好~

點這參與眾籌 我的支付寶:13958686678

一、 前言

  泥瓦匠又和大家見面了,最近兩天我在Code Review ,順便代碼小小的Refactoring(重構)下。先了解這個項目吧,這次解決的是數據源配置優化。因為這web項目中配置數據源的地方很多。例如JDBC要配置數據源,Mybatis要配置數據源,Quartz定時任務要配置數據源,還有Log4j存記錄到數據庫也要配置…

  如題目,興許大家的疑惑看了前面的說明會明白。這次給大家帶來的 數據源配置與優化:log4j 配置數據庫連接池Druid。

  提綱:

  • 二、准備知識
  • 三、正文 開始動手吧
  •      、配置文件
  •      、建數據表
  •      、核心代碼講解
  • 四、結論及下載

二、准備知識

  泥瓦匠也是怕自己說不清楚,又不想把Log4j 和 Durid介紹個遍。那樣會太麻煩。這次主要是項目實戰。所以泥瓦匠也不羅嗦知識准備這塊也就是點到為止。

  Log4j 簡介
  在應用程序中添加日志記錄總的來說基於三個目的
    監視代碼中變量的變化情況,周期性的記錄到文件中供其他應用進行統計分析工作;
    跟蹤代碼運行時軌跡,作為日后審計的依據;
    擔當集成開發環境中的調試器的作用,向文件或控制台打印代碼的調試信息。
  它支持將日志信息輸入到數據庫,這次我們一Mysql為例說明。我們需要Log4j來將調試信息、操作信息等記錄下來,以便后面的審計,這些日志信息包括用戶ID、用戶姓名、操作類、路徑、方法、操作時間、日志信息。

  Druid 簡介

  Druid是Java語言中最好的數據庫連接池。Druid能夠提供強大的監控和擴展功能。不多多介紹了,阿里牛人作品必須精品。詳細介紹在:https://github.com/alibaba/druid/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

 

  泥瓦匠的任務很簡單,目的是為了數據源配置優化,實現數據源配置的唯一性。泥瓦匠也畫了草圖,曾經被人說成畫圖畫出鬼畫符的我告訴大家:沒事,越做越好。如圖,設計簡單草圖就是這樣的。

image

結論:一個項目的配置文件要保持唯一性,就是數據源配置的唯一性。

 

三、正文 開始動手吧

  開始弄吧,為了寫這個東西。我就也搞了個demo項目。泥瓦匠很辛苦的,哈哈送錢的上面支付寶哦。哈哈,泡了杯水,准備說這個項目了。下面,泥瓦匠先給出這個項目的結構圖,這樣我待會講起來不怎么累。邏輯性比較強吧。如圖:

image

  上面很清楚的寫着我需要完成的功能模塊。最后那個test,是一個測試的servlet類。大家一看就明白。我先從配置文件說起吧。

配置文件

  dbConfig.properties 記錄的是最基礎的db配置:url name psd 等,代碼如下:

database.vendor = mysql
db_url = jdbc:mysql://localhost:3307/test
driverClassName= com.mysql.jdbc.Driver
db_user = root
db_password = 123456
showsql= false
devMode = true
validationQuery=SELECT 1

  log4j.properties則是日志的配置,但日志的配置中有一點注意的是如下:

log4j.rootLogger=debug,appender1
log4j.appender.appender1=org.apache.log4j.ConsoleAppender
log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout
log4j.logger.test=INFO, db

# log db setting
log4j.appender.db=org.nsg.dbsetting.MyJDBCAppender
log4j.appender.db.BufferSize=1
log4j.appender.db.sql=insert into operate_log(handclass,method,createtime,loglevel,logmsg) values ('%C','%M','%d{yyyy-MM-dd HH\:mm\:ss}','%p','%m')
log4j.appender.db.layout=org.apache.log4j.PatternLayout

  在這里,我們要注意兩點:

一、設置我們包的下的logger權限,並給予存數據庫的權限。

image

二、db的實現的應用要為你寫的引用類。

# log db setting
log4j.appender.db=org.nsg.dbsetting.MyJDBCAppender

建數據表

然后我們要根據上面配置文件中寫的數據庫和表格我們要對應的建一個名為test的數據庫和一張名為operate_log的表。

/*
Navicat MySQL Data Transfer

Source Server         : Mysql
Source Server Version : 50617
Source Host           : localhost:3307
Source Database       : test

Target Server Type    : MYSQL
Target Server Version : 50617
File Encoding         : 65001

Date: 2014-12-08 18:46:21
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for operate_log
-- ----------------------------
DROP TABLE IF EXISTS `operate_log`;
CREATE TABLE `operate_log` (
  `log_id` int(11) NOT NULL AUTO_INCREMENT,
  `handclass` varchar(100) DEFAULT NULL,
  `method` varchar(100) DEFAULT NULL,
  `createtime` varchar(100) DEFAULT NULL,
  `loglevel` varchar(20) DEFAULT NULL,
  `logmsg` text,
  PRIMARY KEY (`log_id`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8;

這樣我們就可以開始寫代碼了,泥瓦匠是一個很細節的人。這次博客,我主要是講下代碼中的核心點。因為后面我會把項目提供給你們下載。所以,這里點到為止。

泥瓦匠說:點到為止,所謂師父領進門,修行在個人啊。

核心代碼講解:

  MyJDBCAppender.java 用於Log4j的數據庫Session管理[連接池用Druid]。這個肯定是我們得核心思想。這里我就繼承了log4j提供的org.apache.log4j.jdbc.JDBCAppender;然后只要簡單的重寫了closeConnection和getConnection方法。如果獲取Druid數據庫源對象異常的話,我還寫了個 取消初始化 的方法uninitialize。代碼這邊也貼出下,方便大家觀看:

package org.nsg.dbsetting;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.log4j.jdbc.JDBCAppender;
import org.apache.log4j.spi.ErrorCode;
import org.nsg.constant.PropertiesConst;
import org.nsg.exception.JdbcException;
import org.nsg.util.MyProperties;
import org.nsg.util.PropertiesUtil;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

/**
 * @Description  MyJDBCAppender.java
 * 用於Log4j的數據庫Session管理[連接池用Druid]
 * @author 泥沙磚瓦漿木匠
 * @date 2014年12月7日下午1:50:56
 * @version 1.0
 */
public class MyJDBCAppender extends JDBCAppender
{
	/* Druid數據源 */
	private DruidDataSource dataSource;
	
	public MyJDBCAppender()
	{
		super();
	}
	
	@Override
	protected void closeConnection(Connection con)
	{
		try
		{
			/* 如果數據庫連接對象不為空和沒有被關閉的話,關閉數據庫連接 */
			if ( con != null && !con.isClosed())
				con.close();
			
		} 
		catch (SQLException e)
		{
			errorHandler.error("Error closing MyJDBCAppender.closeConnection() 's connection",e,ErrorCode.GENERIC_FAILURE); 
		}
	}

	@Override
	protected Connection getConnection() throws SQLException
	{
		/* 獲取數據庫配置property */
		MyProperties properties = PropertiesUtil.loadPropertyFile(PropertiesConst.DB_CONFIG);
		String className = String.valueOf(properties.getProperty("driverClassName",""));
		String connUrl = String.valueOf(properties.getProperty("db_url",""));
		String uname = String.valueOf(properties.getProperty("db_user",""));
		String psw = String.valueOf(properties.getProperty("db_password",""));

		System.out.println(className);
		System.out.println(connUrl);
		System.out.println(uname);
		System.out.println(psw);
		
		Properties result = new Properties();
		result.put("driverClassName",className);
		result.put("url",connUrl);
		result.put("username",uname);
		result.put("password",psw);
		
		/* 其他配置 自然你也可以自己寫property 然后獲取set */
		result.put("maxActive","30");
		result.put("minIdle","3");

		try
		{
			dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(result);
		}
		catch (Exception e)
		{
			/* Druid數據庫源對象產生失敗后,取消初始化 */
			try {uninitialize();} catch(Exception e2) {}
			throw new JdbcException(e);
		}
		
		return dataSource.getConnection();
	}

	/* 取消初始化 */
	public void uninitialize()
	{
		try
		{
			if (dataSource != null)
				dataSource.close();
		} 
		catch (Exception e)
		{
			throw new JdbcException(String.format("MyJDBCAppender uninitialize fail (%s)",e));
		}
		finally
		{
			super.close();
		}
	} 
	
}

  值得注意的一點是,泥瓦匠為了方便,所以在其中的地方沒有獲取druid連接池的配置。而是直接寫了下面:

/* 其他配置 自然你也可以自己寫property 然后獲取set */
		result.put("maxActive","30");
		result.put("minIdle","3");

  其實這樣寫是不好了,我們可以寫一個druid.properties然后將連接池的配置放入其中。獲取set,for循環set即可。這邊我就不實現了。很簡單哦,泥瓦匠相信你們。

 

最后我演示下,示例代碼:放到tomcat7上,然后運行訪問

image

看到控制台刷出來兩條信息,因為我門設置的是log4j.logger.test=INFO, db。

然后我們去查看數據庫,這邊我用Navicat:

image

 

四、結論及下載

結論:重構很有意思,慢慢來,一點一點來,就行了。細節成就未來。

下載鏈接:

http://pan.baidu.com/s/1hqKN0Le

如以上文章或鏈接對你有幫助的話,別忘了在文章按鈕或到頁面右下角點擊 “贊一個” 按鈕哦。你也可以點擊頁面右邊“分享”懸浮按鈕哦,讓更多的人閱讀這篇文章


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM