Spring中添加 Log4j注解

   参照别人的代码做了个Demo如下:

Spring的加载时自动自行此bean的应用

package cn.com.vnvtrip.spring.log4j.ext;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.BeanPostProcessor;

import cn.com.vnvtrip.spring.log4j.anonation.Logger;

/**
 * Log4j日志注解化的应用 基本原理如下:
 *  通过自定义一个BeanPostProcessor, 在对所有bean初始化之前,
 * 对每一个bean的field进行检查, 是否适用了Logger注解, 如果有, 则调用LogFactory创建一个logger实例.
 *
 * @author longgangbai
 *
 */
public class LogBeanPostProcessor implements BeanPostProcessor {
 /**
  * 初始化之后的操作
  */
 public Object postProcessAfterInitialization(Object bean, String beanName)
   throws BeansException {
  return bean;
 }

 /**
  * 初始化之前的操作的处理
  */
 public Object postProcessBeforeInitialization(Object bean, String beanName)
   throws BeansException {
  List<Class<?>> clazzes = getAllClasses(bean);

  for (Class<?> clazz : clazzes) {
   initializeLog(bean, clazz);
  }
  return bean;
 }

 /**
  * 初始化添加日志功能的
  *
  * @param bean
  * @param clazz
  */
 private void initializeLog(Object bean, Class<? extends Object> clazz) {
  Field[] fiels = clazz.getDeclaredFields();
  for (Field field : fiels) {

   if (field.getAnnotation(Logger.class) == null) {
    continue;
   }
   if (!field.getType().isAssignableFrom(Log.class)) {
    continue;
   }
   // 獲取是否可以方法的属性
   boolean visable = field.isAccessible();
   try {
    // 設置可以属性为可以访问
    field.setAccessible(true);
    field.set(bean, LogFactory.getLog(clazz));
   } catch (Exception e) {
    throw new BeanInitializationException(String.format(
      "初始化logger失败!bean=%s;field=%s", bean, field));
   } finally {
    // 恢复原来的访问修饰
    field.setAccessible(visable);
   }
  }
 }

 /**
  *
  * 獲取制定bean的class以及所有父类的列表,该列表中顺序为从父类中当前类
  *
  * @param bean
  * @return
  */
 private List<Class<?>> getAllClasses(Object bean) {
  Class<? extends Object> clazz = bean.getClass();
  List<Class<?>> clazzes = new ArrayList<Class<?>>();
  while (clazz != null) {
   clazzes.add(clazz);
   clazz = clazz.getSuperclass();
  }
  Collections.reverse(clazzes);
  return clazzes;
 }
}
設置注解类

package cn.com.vnvtrip.spring.log4j.anonation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 添加一個日志注解类
 *
 * @author longgangbai
 *
 */
@Retention(RetentionPolicy.RUNTIME) //运行是编译
@Target( { ElementType.FIELD })  //修饰的字段
public @interface Logger {

}

package cn.com.vnvtrip.spring.log4j.test;

import org.apache.commons.logging.Log;

import cn.com.vnvtrip.spring.log4j.anonation.Logger;

public class LoggAnonation {

 @Logger
 private static Log log;

 public double divide(int a, int b) {
  if (b == 0) {
   log.error("被除数不可以为0");
  } else {
   return a / b;
  }
  return -1;

 }

}

Spring配置:

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans "
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance "
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd ">
 <bean id="logBeanPocessor"
  class="cn.com.vnvtrip.spring.log4j.ext.LogBeanPostProcessor" />
  <bean id="loganonation" class="cn.com.vnvtrip.spring.log4j.test.LoggAnonation"/>
</beans>

 

测试类:

package cn.com.vnvtrip.spring.log4j.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class LogTest {
 public static void main(String[] args) {
  ApplicationContext ctxapp = new ClassPathXmlApplicationContext(
    "applicationContext.xml");
  LoggAnonation logtest = (LoggAnonation) ctxapp.getBean("loganonation");
  double a = logtest.divide(8, 0);
  System.out.println(a);
 }
}

 

 

spring针对编码,log4j的配置;

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <display-name>RESTWebServices</display-name>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:config/application-*.xml</param-value>
  </context-param>
  <listener>
    <listener-class>
  		org.springframework.web.context.ContextLoaderListener
  	</listener-class>
  </listener>
  <servlet>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
    <url-pattern>/service/*</url-pattern>
  </servlet-mapping>
  
    <!-- Filter 定义  -->
    <!-- Character Encoding filter
    CharacterEncodingFilter类具有encoding和forceEncoding两个属性,其中encoding是表示设置request的编码,forceEncoding表示是否同时设置response的编码。
     -->
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    
    <context-param>
      <param-name>log4jConfigLocation</param-name>
      <param-value>classpath:config/log4j.properties</param-value>
   </context-param>
   <context-param>
      <param-name>log4jRefreshInterval</param-name>
      <param-value>6000</param-value>
   </context-param>
	
    <listener>
      <listener-class>
        org.springframework.web.util.Log4jConfigListener
      </listener-class>
   </listener> 
</web-app>

 log4j.properties文件内容:

#log4j.rootLogger = [ level ] , appenderName, appenderName, ...
log4j.rootLogger = INFO, console, R
#level=INFO,all can be output
#console is set to be a ConsoleAppender
log4j.appender.console = org.apache.log4j.ConsoleAppender
#console have four patterns
#org.apache.log4j.HTMLLayout
#org.apache.log4j.PatternLayout
#org.apache.log4j.SimpleLayout
#org.apache.log4j.TTCCLayout
log4j.appender.console.layout = org.apache.log4j.PatternLayout
#define the output type
log4j.appender.console.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] %m%n
#file is set to output to a extra file
log4j.appender.R = org.apache.log4j.RollingFileAppender
#the absolute route of the log4j file
log4j.appender.R.File = /log.txt
#the size
log4j.appender.R.MaxFileSize = 500KB
#back up a file
log4j.appender.R.MaxBackupIndex = 1
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%c]-[%p] - %m%n

 

log4j日志整合输出(slf4j+commonslog+log4j+jdklogger)

J2EE项目中,经常会用到很多第三方的开源组件和软件,这些组件都使用各自的日志组件,比较常用的包括slf4j,common-log, log4j等,很多老的开源软件(包括TOMCAT)使用的是JDK14-LOGGER。这些日志都有自己独立的配置,或只是其中一些可以整合。但是在项目实际部署的时候,需要把所有开源软件和项目程序的各种日志都整合到日志文件中输出,包括tomcat。

 

  本文介绍使用log4j作为日志组件,commons-log, slf4j 作为整合器,同时使用slf4j桥接jdk14-logger输出到log4j日志器。总的来说,达到项目中所有使用这四中日志输出的都统一使用log4j输出。

 

1.日志需要的包依赖(maven dependency):

 

Xml代码    收藏代码
  1. <properties>  
  2.     <slf4j.version>1.7.2</slf4j.version>  
  3.     <log4j.version>1.2.17</log4j.version>  
  4. </properties>  
  5. <!-- LOGGING begin -->  
  6. <!-- slf4j -->  
  7. <dependency>  
  8.     <groupId>org.slf4j</groupId>  
  9.     <artifactId>slf4j-api</artifactId>  
  10.     <version>${slf4j.version}</version>  
  11. </dependency>  
  12.   
  13. <!-- slf4j-log4j绑定 -->  
  14. <dependency>  
  15.     <groupId>org.slf4j</groupId>  
  16.     <artifactId>slf4j-log4j12</artifactId>  
  17.     <version>${slf4j.version}</version>  
  18. </dependency>  
  19.   
  20. <!-- common-logging 实际调用slf4j -->  
  21. <dependency>  
  22.     <groupId>org.slf4j</groupId>  
  23.     <artifactId>jcl-over-slf4j</artifactId>  
  24.     <version>${slf4j.version}</version>  
  25. </dependency>  
  26.   
  27. <!-- java.util.logging 实际调用slf4j -->  
  28. <dependency>  
  29.     <groupId>org.slf4j</groupId>  
  30.     <artifactId>jul-to-slf4j</artifactId>  
  31.     <version>${slf4j.version}</version>  
  32. </dependency>  
  33.   
  34. <!-- log4j -->  
  35. <dependency>  
  36.     <groupId>log4j</groupId>  
  37.     <artifactId>log4j</artifactId>  
  38.     <version>${log4j.version}</version>  
  39. </dependency>  
  40. <!-- LOGGING end -->  

 

 

2.log4j配置

log4j的配置较简单,使用通常的log4j.properties文件配置就可以,一般放到classes下就OK,你可以在web.xml中加入常量配置配置文件路径。该常量用于filter加载的时候加载日志配置。

 

 

Xml代码    收藏代码
  1. <!--tomcat启动,filter载入的Log4j配置文件位置 -->  
  2. <context-param>  
  3.     <param-name>log4jConfigLocation</param-name>  
  4.     <param-value>/WEB-INF/log4j.properties</param-value>  
  5. </context-param>  
  6.   
  7. <!--Spring默认刷新Log4j配置文件的间隔,单位为millisecond, 用于在线动态修改log4j日志 -->  
  8. <context-param>  
  9.     <param-name>log4jRefreshInterval</param-name>  
  10.     <param-value>30000</param-value>  
  11. </context-param>  

   一般情况下,使用Spring提供的org.springframework.web.util.Log4jConfigListener负载在tomcat启动的时候加载log4j配置托管spring的日志输出配置。

 

   log4j.properties

 

Python代码    收藏代码
  1. log4j.rootCategory=INFO,stdout,logfile  
  2.   
  3. # Spring framework log level  
  4. log4j.logger.org.springframework=INFO  
  5. # spring modules log level  
  6. #log4j.logger.org.springmodules=DEBUG  
  7. # Hibernate log level  
  8. # log4j.logger.org.hibernate=DEBUG  
  9. log4j.logger.org.hibernate.SQL=DEBUG  
  10. # Quartz log level  
  11. #log4j.logger.org.quartz=INFO  
  12. # Tomcat,commons... etc log level  
  13. #log4j.logger.org.apache=INFO  
  14. # Application log level  
  15. #sql and execute time  
  16.   
  17. # log4jdbc  
  18. log4j.logger.jdbc.sqltiming=INFO  
  19. log4j.logger.jdbc.audit=OFF  
  20. log4j.logger.jdbc.resultset=OFF  
  21. log4j.logger.jdbc.sqlonly=INFO  
  22.   
  23. log4j.appender.stdout=org.apache.log4j.ConsoleAppender  
  24. log4j.appender.stdout.layout=org.apache.log4j.PatternLayout  
  25. log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n  
  26.   
  27. #\u4e3b\u65e5\u5fd7\u6587\u4ef6  
  28. log4j.appender.logfile=org.apache.log4j.DailyRollingFileAppender  
  29. log4j.appender.logfile.File=logs/intergration.log  
  30. log4j.appender.logfile.DatePattern=.yyyy-MM-dd  
  31. log4j.appender.logfile.layout=org.apache.log4j.PatternLayout  
  32. log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - <%m>%n  

 

 

 

 

3. 整合日志

  • slf4j的日志会自动根据slf4j-log4j12-xxx.jar输出日志到log4j,无需配置。
  • commons-log的日志会自动根据jcl-over-slf4j转到log4j输出,无需配置
  • jdk14-logger的日志输出(如:tomcat,restlet等软件)可以根据jul-to-slf4j提供的Handler转移日志输出到slf4j,然后又slf4j转log4j输出。但是需要配置或编程方式设置

配置方式整合:

建立jdk14-logger的配置文件logger.properties.加入Hander配置:

handlers = org.slf4j.bridge.SLF4JBridgeHandler

然后在启动程序或容器的时候加入JVM参数配置JDK日志只是用SLF4JBridgeHandler处理:

-Djava.util.logging.config.file=/path/logger.properties

 

 

我不太喜欢这种方式,需要外部修改,麻烦,耦合性强。所以推荐是用编程方式。

 

编程方式:

扩展Spring提供的org.springframework.web.util.Log4jConfigListener,在TOMCAT启动的时候编程方式设置JDK的日志只是用SLF4JBridgeHandler进行处理。如果你不是WEB程序就更简单了,直接在程序MAIN方式里面设置就OK。

APP程序DEMO:

 

Java代码    收藏代码
  1. public class CommonLogAndLog4j {  
  2.   
  3.     private static final Log log = LogFactory.getLog(CommonLogAndLog4j.class);  
  4.     private static final Logger log4jLogger = Logger.getLogger(CommonLogAndLog4j.class);  
  5.     private static final java.util.logging.Logger jdkLogger = java.util.logging.Logger  
  6.             .getLogger(CommonLogAndLog4j.class.getName());  
  7.   
  8.     private static final org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger(CommonLogAndLog4j.class);  
  9.   
  10.     // -Djava.util.logging.config.file=D:/workshop/log-intergration/src/logging.properties  
  11.     public static void main(String[] args) {  
  12.         installJulToSlf4jBridge();  
  13.         log.info("CommonsLog日志输出");  
  14.         log4jLogger.info("Log4j日志输出");  
  15.         jdkLogger.info("JDK14日志输出");  
  16.         slf4jLogger.info("slft4j日志输出");  
  17.     }  
  18.   
  19.     public static void installJulToSlf4jBridge() {  
  20.         SLF4JBridgeHandler.removeHandlersForRootLogger();  
  21.         SLF4JBridgeHandler.install();  
  22.     }  
  23.   
  24. }  

 

 

Webapp程序:

LoggerIntergrationListener.class

Java代码    收藏代码
  1. /** 
  2.  * 扩展Spring的Log4jConfigListener,在容器启动的时候,桥接JDK14的输出到slf4j-logger 
  3.  *  
  4.  * @author zhangpu 
  5.  */  
  6. public class LoggerIntergrationListener extends Log4jConfigListener {  
  7.       
  8.     @Override  
  9.     public void contextInitialized(ServletContextEvent event) {  
  10.         installJulToSlf4jBridge();  
  11.         event.getServletContext().log("Install Jdk-util-logger to slf4j success.");  
  12.         super.contextInitialized(event);  
  13.     }  
  14.   
  15.       
  16.     private void installJulToSlf4jBridge() {  
  17.         SLF4JBridgeHandler.removeHandlersForRootLogger();  
  18.         SLF4JBridgeHandler.install();  
  19.     }  
  20.   
  21. }  

 

web.xml配置

Xml代码    收藏代码
  1. <!--Intergration log4j/slf4j/commons-logger/jdk14-logger to log4j -->  
  2. <listener>  
  3.     <listener-class>com.feinno.framework.common.web.support.LoggerIntergrationListener</listener-class>  
  4. </listener>  

 

OK,over!~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值