zoukankan      html  css  js  c++  java
  • 方法级别的java日志输出控制(一)

    前面学习了log4j以及log4j2 java日志控制,通过配置可以实现java日志的输出级别,输出位置,输出格式等日志控制,甚至可通过配置控制不同java类的日志输出方式。在大型web系统中,这些基本的日志控制可能还是不够的。由于日志输出是非常耗费资源的事情,特别在大型应用特定场景中。所以一般情况下只做warn或者只做error级别的日志输出。然而,我们可能需要更加精细的日志控制,比如说想控制每一个方法的输出级别,同时想在打印错误日志的时候把某一个方法的输入参数也打印出来,以便更方便的查找问题的所在。本文将介绍通过配置文件和AOP技术控制方法级别的日志输出。

    先看LogActive日志类:

    package com.lf.testLog4j.aop;
    
    import com.google.gson.Gson;
    import com.lf.testLog4j.Util.PropertiesUtil;
    import com.lf.testLog4j.common.CommonLogUtil;
    import com.lf.testLog4j.domain.ConfigLog;
    import org.apache.commons.lang.StringUtils;
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.aspectj.lang.JoinPoint;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Properties;
    
    /**
     * Created by lufei3 on 2015/7/14.
     */
    public class LogActive {
        private static final Logger logger = LogManager.getLogger(LogActive.class);
        //前切入方法,该方法会在所有切入点之前执行。
        public void before(JoinPoint jp){
            //从配置文件读取配置信息
            Properties prop = PropertiesUtil.getProperties("/ConfigCenter.properties");
            Map<String, String> map = new HashMap<String, String>((Map) prop);
            Gson gson = new Gson();
            ConfigLog configLog = null;
            String cName = jp.getThis().toString();
            Object[] args = jp.getArgs();  //获得切入点参数列表
            String className = cName.substring(cName.lastIndexOf(".")+1,cName.lastIndexOf("@"));
            String methodName = jp.getSignature().getName();   //获得方法名
            String key = className + "." + methodName;
            //获取配置信息
            String configValue = map.get(key);
            try {
                configLog = gson.fromJson(configValue,ConfigLog.class);
            } catch (Exception e) {
                logger.error("Gson Format Exception!! logLevel:{}",configValue);
                e.printStackTrace();
                return;
            }
            if(configLog == null) {
                return;
            }
            //通过配置信息控制日志输出
            String logLevel = configLog.getLevel();
            int offset = configLog.getOn();
            if(StringUtils.isBlank(logLevel)){
                logger.warn("method:{} log not config", key);
                return;
            }
            if(CommonLogUtil.isInfoEnable(logLevel,offset)) {
                logger.info("====Method:{};", key);
                if(args.length <=0){
                    logger.info("===={}方法没有参数", methodName);
                } else{
                    for(int i=0; i<args.length; i++){
                        logger.info("====参数 {}:{} ", (i + 1), args[i]);
                    }
                }
            }
        }
        public void after(){
            logger.info("调用完毕!!");
        }
    }
    

      下面看具体配置信息ConfigCenter.properties:

    TestLogAOP.test={"level":"TRACE","on":0}
    TestLogAOP.test2={"level":"TRACE","on":1}
    

      配置说明执行test()方法的日志开关是0,即不打印日志;test2方法的日志级别是trace,开关为1,即可以打印trace级别的日志。而trace比info级别高,所以在LogActive 方法里info级别的日志是可以打印的。而如果level为warn或者error则info级别的日志就不会输出。

    CommonLogUtil类是用来确定是否可以输出info级别的日志:

    package com.lf.testLog4j.common;
    
    /**
     * Created by lufei3 on 2015/7/20.
     */
    public class CommonLogUtil {
        public static boolean isInfoEnable(String logLevel,int offset) {
            if (offset == 1&&(logLevel.equalsIgnoreCase(LogLevelEnum.INFO_LEVEL.getLogLevel())
                    ||logLevel.equalsIgnoreCase(LogLevelEnum.DEBUG_LEVEL.getLogLevel())
                    ||logLevel.equalsIgnoreCase(LogLevelEnum.TRACE_LEVEL.getLogLevel()))){
                return true;
            }
            return false;
        }
    }
    

      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" xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"
           default-autowire="byName">
        <bean id="logActive" class="com.lf.testLog4j.aop.LogActive"></bean> <!--将日志类注入到bean中。-->
        <bean id="testLogAOP" class="com.lf.testLog4j.service.TestLogAOP"></bean>
    
        <aop:aspectj-autoproxy proxy-target-class="true"/>
        <aop:config>
            <!--拦截service层的所有方法-->
            <aop:pointcut id="service" expression="execution(* com.lf.testLog4j.service.*.*(..))"/>
            <aop:aspect id="log" ref="logActive">
                <aop:before pointcut-ref="service" method="before"/>
                <aop:after pointcut-ref="service" method="after"/>
            </aop:aspect>
        </aop:config>
    </beans>
    

     TestLogAOP类:

    package com.lf.testLog4j.service;
    
    import org.springframework.stereotype.Component;
    
    /**
     * Created by lufei3 on 2015/7/14.
     */
    @Component
    public class TestLogAOP {
        public void test(){
            System.out.println("测试类的test方法被调用");
        }
        public void test2() {
            System.out.println("测试2的方法被调用!");
        }
    }
    

      最后main方法:

    package com.lf.testLog4j;
    
    import com.lf.testLog4j.service.TestLogAOP;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    /**
     * Created by lufei3 on 2015/7/14.
     */
    
    public class LogAOPMain {
        @Autowired
        public static void main(String... args) {
            ApplicationContext act = new ClassPathXmlApplicationContext("spring/spring-config.xml");
            TestLogAOP testLogAOP = (TestLogAOP) act.getBean("testLogAOP");
            testLogAOP.test();
            testLogAOP.test2();
        }
    }
    

      输出:

    测试类的test方法被调用
    13:43:35.673 [main] INFO  com.lf.testLog4j.aop.LogActive - 调用完毕!!
    13:43:35.713 [main] INFO  com.lf.testLog4j.aop.LogActive - ====Method:TestLogAOP.test2;
    13:43:35.713 [main] INFO  com.lf.testLog4j.aop.LogActive - ====test2方法没有参数
    测试2的方法被调用!
    13:43:35.714 [main] INFO  com.lf.testLog4j.aop.LogActive - 调用完毕!!
    

      可以看出日志根据配置文件打印了TestLogAOP.test2方法调用前后的日志输出。

    本文地址:http://www.cnblogs.com/danseqianbi/p/4685570.html

  • 相关阅读:
    数组中的每一个对象执行一次方法:makeObjectsPerformSelector
    $.each() each
    JQ js选择节点操作
    Sublime Text 3 快捷键
    TotoiseSVN的基本使用方法
    Hbuilder快捷键
    获取网页内容区域各种高/宽汇总
    TP操作
    xhr接收php://output的二进制文件,并转换成excel表格
    Go语言的%d,%p,%v等占位符的使用
  • 原文地址:https://www.cnblogs.com/danseqianbi/p/4685570.html
Copyright © 2011-2022 走看看