`
javasee
  • 浏览: 964613 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

springside3.*中log4j和java.util.concurrent的结合使用

阅读更多

 在springside3.*中的showcase案例中,有一个把log4j的日志存入数据库的演示,下面是我对这个案例的学习笔记。
1、我们首先来看下log4j相关日志的配置:

#Async Database Appender (Store business message)
log4j.appender.DB
= org.springside.examples.showcase.log.appender.QueueAppender
log4j.appender.DB.QueueName
= dblog

#Demo level with Async Database appender 
log4j.logger.DBLogExample
= INFO,Console,DB
log4j.additivity.DBLogExample
= false


其中org.springside.examples.showcase.log.appender.QueueAppender就是对ssLog4j日 志的一个扩展,而日志的event(里面是日志的内容)是存放在一个BlockingQueue中,当有多个日志需要分别存入不同的地方时,就根据 QueryName来区分。
2、接下来看一下org.springside.examples.showcase.log.appender.QueueAppender里面的内容:

/** */ /**
 * Copyright (c) 2005-2009 springside.org.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * 
 * $Id: QueueAppender.java 1189 2010-09-01 17:24:12Z calvinxiu $
 
*/

package  org.springside.examples.showcase.log.appender;

import  java.util.concurrent.BlockingQueue;

import  org.apache.log4j.helpers.LogLog;
import  org.apache.log4j.spi.LoggingEvent;
import  org.springside.examples.showcase.queue.QueuesHolder;

/** */ /**
 * 轻量级的Log4j异步Appender.
 * 
 * 将所有消息放入QueueManager所管理的Blocking Queue中.
 * 
 * 
@see  QueuesHolder
 * 
 * 
@author  calvin
 
*/

public   class  QueueAppender  extends  org.apache.log4j.AppenderSkeleton  {

    
protected  String queueName;

    
protected  BlockingQueue < LoggingEvent >  queue;

    
/** */ /**
     * AppenderSkeleton回调函数, 事件到达时将时间放入Queue.
     
*/

    @Override
    
public   void  append(LoggingEvent event)  {
        
if  (queue  ==   null {
            queue 
=  QueuesHolder.getQueue(queueName);
        }


        
boolean  sucess  =  queue.offer(event);

        
if  (sucess)  {
            LogLog.debug(
" put event to queue success: "   +   new  LoggingEventWrapper(event).convertToString());

        }
  else   {
            LogLog.error(
" Put event to queue fail: "   +   new  LoggingEventWrapper(event).convertToString());
        }

    }


    
/** */ /**
     * AppenderSkeleton回调函数,关闭Logger时的清理动作.
     
*/

    
public   void  close()  {
    }


    
/** */ /**
     * AppenderSkeleton回调函数, 设置是否需要定义Layout.
     
*/

    
public   boolean  requiresLayout()  {
        
return   false ;
    }


    
/** */ /**
     * Log4j根据getter/setter从log4j.properties中注入同名参数.
     
*/

    
public  String getQueueName()  {
        
return  queueName;
    }


    
/** */ /**
     * 
@see  #getQueueName()
     
*/

    
public   void  setQueueName(String queueName)  {
        
this .queueName  =  queueName;
    }

}

这是对Log4j扩展的标准做法,继承abstract class AppenderSkeleton,实现它的abstract  protected   void append(LoggingEvent event) 方法。
而这个方法的实现很简单,就是根据queueName从queuesHolder中取出一个 BlockingQueue<LoggingEvent>,然后把LoggerEvent塞到这个BlockingQueue中去,关于 queuesHolder,下面会讲到。到这为止,log4j的活就完成了,下面的都是concurrent的事了。
3、让我们转到spring的配置文件中,看看springside是如何接收下面的工作,下面是applicationContext-log.xml的片段:

     <!--  消息Queue管理器 -->
    
< bean  class = " org.springside.examples.showcase.queue.QueuesHolder " >
        
< property name = " queueSize "  value = " 1000 "   />
    
</ bean >

    
<!--  读出Queue中日志消息写入数据库的任务  -->
    
< bean id = " jdbcLogWriter "   class = " org.springside.examples.showcase.log.appender.JdbcLogWriter " >
        
< property name = " queueName "  value = " dblog "   />
        
< property name = " batchSize "  value = " 10 "   />
        
< property name = " sql " >
            
< value >
                insert into SS_LOG(THREAD_NAME,LOGGER_NAME,LOG_TIME,LEVEL,MESSAGE)
                values(:thread_name,:logger_name,:log_time,:level,:message)
            
</ value >
        
</ property >
    
</ bean >


我们先从简单的下手,先看QueuesHolder:

private   static  ConcurrentMap < String, BlockingQueue >  queueMap  =   new  MapMaker().concurrencyLevel( 32 ).makeMap(); // 消息队列

/** */ /**
     * 根据queueName获得消息队列的静态函数.
     * 如消息队列还不存在, 会自动进行创建.
     
*/

    
public   static   < T >  BlockingQueue < T >  getQueue(String queueName)  {
        BlockingQueue queue 
=  queueMap.get(queueName);

        
if  (queue  ==   null {
            BlockingQueue newQueue 
=   new  LinkedBlockingQueue(queueSize);

            
// 如果之前消息队列还不存在,放入新队列并返回Null.否则返回之前的值.
            queue  =  queueMap.putIfAbsent(queueName, newQueue);
            
if  (queue  ==   null {
                queue 
=  newQueue;
            }

        }

        
return  queue;
    }

其实这个类很简单,就是一个map,key就是上面log4j配置文件中的queueName,value就是一个BlockingQueue,这样就可以存放多个日志queue,做不同的处理。
4、下面这个是重头戏,先把JdbcLogWriter的代码全贴出来:

/** */ /**
 * Copyright (c) 2005-2009 springside.org.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * 
 * $Id: JdbcAppenderTask.java 353 2009-08-22 09:33:28Z calvinxiu
 
*/

package  org.springside.examples.showcase.log.appender;

import  java.util.HashMap;
import  java.util.List;
import  java.util.Map;

import  javax.annotation.Resource;
import  javax.sql.DataSource;

import  org.apache.log4j.spi.LoggingEvent;
import  org.springframework.dao.DataAccessException;
import  org.springframework.dao.DataAccessResourceFailureException;
import  org.springframework.jdbc.core.namedparam.SqlParameterSource;
import  org.springframework.jdbc.core.namedparam.SqlParameterSourceUtils;
import  org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
import  org.springframework.transaction.PlatformTransactionManager;
import  org.springframework.transaction.TransactionStatus;
import  org.springframework.transaction.support.TransactionCallbackWithoutResult;
import  org.springframework.transaction.support.TransactionTemplate;
import  org.springside.examples.showcase.queue.BlockingConsumer;

import  com.google.common.collect.Lists;
import  com.google.common.collect.Maps;

/** */ /**
 * 将Queue中的log4j event写入数据库的消费者任务.
 * 
 * 即时阻塞的读取Queue中的事件,达到缓存上限后使用Jdbc批量写入模式.
 * 如需换为定时读取模式,继承于PeriodConsumer稍加改造即可.
 * 
 * 
@see  BlockingConsumer
 * 
 * 
@author  calvin
 
*/

public   class  JdbcLogWriter  extends  BlockingConsumer  {

    
protected  String sql;
    
protected   int  batchSize  =   10 ;

    
protected  List < LoggingEvent >  eventsBuffer  =  Lists.newArrayList();
    
protected  SimpleJdbcTemplate jdbcTemplate;
    
protected  TransactionTemplate transactionTemplate;

    
/** */ /**
     * 带Named Parameter的insert sql.
     * 
     * Named Parameter的名称见AppenderUtils中的常量定义.
     
*/

    
public   void  setSql(String sql)  {
        
this .sql  =  sql;
    }


    
/** */ /**
     * 批量读取事件数量, 默认为10.
     
*/

    
public   void  setBatchSize( int  batchSize)  {
        
this .batchSize  =  batchSize;
    }


    
/** */ /**
     * 根据注入的DataSource创建jdbcTemplate.
     
*/

    @Resource
    
public   void  setDataSource(DataSource dataSource)  {
        jdbcTemplate 
=   new  SimpleJdbcTemplate(dataSource);
    }


    
/** */ /**
     * 根据注入的PlatformTransactionManager创建transactionTemplate.
     
*/

    @Resource
    
public   void  setDefaultTransactionManager(PlatformTransactionManager defaultTransactionManager)  {
        transactionTemplate 
=   new  TransactionTemplate(defaultTransactionManager);
    }


    
/** */ /**
     * 消息处理函数,将消息放入buffer,当buffer达到batchSize时执行批量更新函数.
     
*/

    @Override
    
protected   void  processMessage(Object message)  {
        LoggingEvent event 
=  (LoggingEvent) message;
        eventsBuffer.add(event);

        
if  (logger.isDebugEnabled())  {
            logger.debug(
" get event: {} " new  LoggingEventWrapper(event).convertToString());
        }


        
// 已到达BufferSize则执行批量插入操作
         if  (eventsBuffer.size()  >= <sp
1
3
分享到:
评论

相关推荐

    springside3.0.zip

    9. **日志管理**:SpringSide 3.0 使用Log4j或Logback作为日志框架,提供了灵活的日志配置和丰富的日志记录功能。 10. **持续集成**:SpringSide 3.0 考虑到持续集成的重要性,推荐使用Hudson或Jenkins进行持续构建...

    springside-core-4.1.0.GA.jar

    springside-core-4.1.0.GA.jar是一个重要的Java库,它在Java开发领域中扮演着核心角色,尤其对于那些使用Spring框架的项目。这个jar包不仅包含了springside-core-4.1.0.GA的主要功能,还兼容了springside-core-3.3.4...

    springside-4.0.0.GA.zip

    4. **构建工具**:可能包含了Maven或Gradle配置,展示了如何使用构建工具来管理和构建Spring项目,以及如何集成持续集成工具如Jenkins。 5. **单元测试**:SpringSide强调TDD(测试驱动开发),因此在项目中会有...

    springside-1.0-M3.zip

    标题 "springside-1.0-M3.zip" 暗示了这是一个关于SpringSide项目的早期版本,具体为1.0 Milestone 3(M3)。...对于Java开发者来说,研究SpringSide有助于提升Spring框架的使用技能和项目管理能力。

    有springside4.2.3-GA.jar 包

    SpringSide 4.2.3-GA作为其稳定版本,集成了许多最新的技术和最佳实践,如Spring 4.x,Hibernate 4.x,Guava,SLF4J等,确保了项目的现代化和高效性。 在springside4-4.2.3.GA中,我们可以看到以下主要模块: 1. *...

    springside4-4.2.3.GA

    《SpringSide4-4.2.3.GA:构建高效Java企业级应用的基石》 SpringSide项目,作为Java开发中的一个强大工具,是基于Spring Framework的快速开发平台。SpringSide 4.2.3.GA版本是该项目的一个稳定版本,它提供了完整...

    springside3.3完整版

    本版本,即“springside3.3”,是专为MyEclipse集成环境设计的,包含了完整的功能代码,方便开发者在MyEclipse中进行开发和调试。同时,它还附带了数据.sql文件,意味着我们可以直接导入数据库,快速搭建项目环境。 ...

    springside3.0.1.zip

    通过对SpringSide 3.0.1源代码的深入研究,不仅可以加深对Spring框架的理解,还能了解到现代Java企业级开发的各种最佳实践和工具使用。这是一次难得的学习和提升技术的机会,对于任何想要成为专业Java开发者的人来说...

    SpringSide3-core-3.3.4

    总的来说,SpringSide3-core-3.3.4及其扩展包是面向Java开发者的强大工具,它通过精简和优化Spring框架的使用,降低了开发复杂度,同时提供了丰富的功能,使得开发者可以更专注于业务逻辑,提升开发效率。...

    springside4-4.1.0.GA

    《SpringSide 4.1.0.GA:深入探索企业级Java开发的得力助手》 SpringSide项目,作为一个开源的Java开发框架,是许多开发者在进行企业级应用开发时的首选工具。SpringSide 4.1.0.GA版本是该项目的一个稳定版本,它在...

    使用SpringSide_3.1.4.3开发Web项目的全过程

    SpringSide框架是针对Java Web应用的一个完整解决方案,它集成了Spring框架的核心功能,并在此基础上进行了扩展和优化,提供了包括Web层、业务逻辑层、数据访问层等全方位的支持。SpringSide 3.1.4.3作为当时较为...

    SpringSide4

    SpringSide4中的Web模块展示了如何使用Spring MVC构建RESTful API和服务端模板渲染应用。 5. **Bean的生命周期管理**:Spring负责Bean的创建、初始化、装配和销毁。通过@Scope注解控制Bean的作用域,如单例...

    springside3源码及jar

    2. **注释与文档**:springside3的源码中包含了丰富的Javadoc注释,便于开发者理解代码功能和使用方法。同时,项目还提供了详细的API文档,有助于快速上手。 三、springside3的jar包使用 1. **依赖管理**:...

    springside_4jar.rar

    这个名为"springside_4jar.rar"的压缩包文件,包含了SpringSide 4的全部组件,是开发者们学习和使用SpringSide 4的重要资源。 1. **SpringSide简介** SpringSide是针对Java开发者的一个轻量级、模块化的快速开发...

    Springside-core-4.1.0/Springside-core-4.1.0

    SpringSide是Java开发中的一款轻量级框架,它基于Spring框架,旨在简化企业级应用的开发流程。本文将深入探讨SpringSide-core-4.1.0的核心特性,以及其在实际项目中的应用。 一、SpringSide概述 SpringSide是一款...

    springside-core.rar

    4. **日志管理**:集成常见的日志框架,如Log4j或Logback,提供统一的日志接口和配置,简化日志的使用。 5. **国际化支持**:提供国际化资源管理,使得应用程序可以根据用户语言环境展示相应的信息。 6. **代码...

    springside4

    10. **日志管理**:SpringSide4利用Logback或Log4j进行日志记录,方便开发者追踪和调试问题。 总的来说,SpringSide4是Java开发者的一个强大工具,它简化了Spring的使用,提供了优秀的项目模板,同时融入了最佳实践...

    springside3.3.4 使用方法

    ### springside3.3.4使用方法与SSH整合详解 #### 一、Springside简介 Springside项目是基于Spring框架的一个应用架构示例,它提供了一套完整的开发模式来构建企业级Java Web应用程序。Springside 3.3.4版本作为一...

    springside3

    在本次讨论中,我们将深入探讨springside3-core-3.3.4.jar这一核心组件,它是SpringSide 3项目的基石,包含了项目的核心功能和模块。 1. **SpringSide 3概述**: SpringSide 3 是由中国的Java社区开发的一个开源...

    springside-core-4.2.2.GA相关jar包

    3. **自动化构建工具**:SpringSide通常与Maven或Gradle等自动化构建工具结合使用,以管理项目的依赖关系和构建过程。在4.2.2.GA版本中,可能已经优化了这些集成,确保开发者可以轻松地构建和测试项目。 4. **代码...

Global site tag (gtag.js) - Google Analytics