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

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

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

若是個人幫到了你,是否樂意捐助一下或請一杯啤酒也好呢?有你支持,乾的更好~mysql

點這參與衆籌 個人支付寶:13958686678git

1、 前言

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

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

  提綱:sql

  • 2、準備知識
  • 3、正文 開始動手吧
  •      、配置文件
  •      、建數據表
  •      、核心代碼講解
  • 4、結論及下載

2、準備知識

  泥瓦匠也是怕本身說不清楚,又不想把Log4j 和 Durid介紹個遍。那樣會太麻煩。此次主要是項目實戰。因此泥瓦匠也不羅嗦知識準備這塊也就是點到爲止。數據庫

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

  Druid 簡介編程

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

 

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

image

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

 

3、正文 開始動手吧

  開始弄吧,爲了寫這個東西。我就也搞了個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

  在這裏,咱們要注意兩點:

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

image

2、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

 

4、結論及下載

結論:重構頗有意思,慢慢來,一點一點來,就好了。細節成就將來。

下載連接:

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

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

相關文章
相關標籤/搜索