1.log4j

1 log4j

1.1 Log4j简介

使用System.out.println的局限性

无法在不修改代码前提下,控制日志开关

1.2 示例1

  1. 导入log4j的jar包(log4j-1.2.17.jar)
  2. Log4jTest
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

public class Log4jTest {
	// 得到一个专属于这个类的日志记录器
	private static Logger logger = Logger.getLogger(Log4jTest.class);

	public static void main(String[] args) {
		// 使用默认的配置信息,不需要log4j.properties
		// 该方法就是给rootLogger默认appender值。configure源码如下
		// Logger root = Logger.getRootLogger();
		// root.addAppender(new ConsoleAppender(new
		// PatternLayout(PatternLayout.TTCC_CONVERSION_PATTERN)));
		BasicConfigurator.configure();
		logger.debug("my first log4j info");
	}
}

1.3 Log4J日志级别

1.3.1 代码

  1. 在src下建立db.properties文件
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///log4j
username=log4j
password=admin
  1. Configure:使用不同日志级别打印日志
ackage cd.itcast.log4j;
import java.io.IOException;
import java.util.Properties;
public class Configure {
  // 同样,首先得到和这个类绑定的Logger实例
  private static Logger log = Logger.getLogger(Configure.class);

  public void config() {
      log.info("using default db.properties");
       config("db.properties");
  }

  public void config(String resourceName) {
      log.info("using config file in classpath:" + resourceName);
      try {
          Properties prop = new Properties();
          prop.load(this.getClass().getClassLoader().getResourceAsStream(resourceName));
          log.debug("load properties file success");
          for (String key : prop.stringPropertyNames()) {
              String value = prop.getProperty(key);
              // doSomeConfigWorkUseKeyAndValue(key,value)
              log.debug("[properties] " + key + " : " + value);
          }
      } catch (Exception e) {
          log.error("log properties file failed", e);
      }
  }
}
  1. LogTest2:客户端,调用debug与info方法
package cd.itcast.log4j;
import org.apache.log4j.BasicConfigurator;
import org.junit.Test;
public class LogTest2 {

  public void testLog2(){
      BasicConfigurator.configure();
      Configure conf=new Configure();
      conf.config();
  }
  public static void main(String[] args) {
	new LogTest2().testLog2();
  }
}
  1. 控制台输出
0 [main] INFO cd.itcast.log4j.Configure  - using default db.properties
0 [main] INFO cd.itcast.log4j.Configure  - using config file in classpath:db.properties
0 [main] DEBUG cd.itcast.log4j.Configure  - load properties file success
0 [main] DEBUG cd.itcast.log4j.Configure  - [properties] driverClass : com.mysql.jdbc.Driver
0 [main] DEBUG cd.itcast.log4j.Configure  - [properties] url : jdbc:mysql:///log4j
0 [main] DEBUG cd.itcast.log4j.Configure  - [properties] password : admin
0 [main] DEBUG cd.itcast.log4j.Configure  - [properties] username : log4j
  1. testLog2:客户端,调用error方法
package cd.itcast.log4j;
import org.apache.log4j.BasicConfigurator;
import org.junit.Test;
public class LogTest2 {

  @Test
  public void testLog2(){
      BasicConfigurator.configure();
      Configure conf=new Configure();
      //故意读一个不存在的日志
      conf.config("aa.properties");
  }
}
  1. 控制台输出:既打印error日志,又打印了错误的栈(类似e.printStack()的效果)
0 [main] INFO cd.itcast.log4j.Configure  - using config file in classpath:aa.properties
16 [main] ERROR cd.itcast.log4j.Configure  - log properties file failed
java.lang.NullPointerException
at java.util.Properties$LineReader.readLine(Properties.java:418)
at java.util.Properties.load0(Properties.java:337)
at java.util.Properties.load(Properties.java:325)
at cd.itcast.log4j.Configure.config(Configure.java:20)
  1. 如果不想打印错误栈信息,在调用Logger.error方法的时候,不要把错误作为第二个参数传入方法即可
//log.error("log properties file failed", e);
log.error("log properties file failed");

1.3.2 扩展

  1. 日志级别顺序
debug<info<warn<error<fatal<off
  1. 日志级别作用
package cd.itcast.log4j;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.junit.Test;
public class LogTest2 {

  @Test
  public void testLog2(){
      BasicConfigurator.configure();
      //设置根日志的日志级别为Level.INFO,即只有Level.INFO及其以上级别的日志生效
      //默认情况下,rootLogger的日志级别被设置为了Level.DEBUG
      Logger.getRootLogger().setLevel(Level.INFO);
      Configure conf=new Configure();
      conf.config();
  }
}
  1. 控制台输出:debug级别的日志被屏蔽
0 [main] INFO cd.itcast.log4j.Configure  - using default db.properties
0 [main] INFO cd.itcast.log4j.Configure  - using config file in classpath:db.properties
  1. 日志记录器(Logger)的层次结构
//1. 此代码真正含义为,创建了一个名为cd.itcast.log4j.Configure的日志记录器(Logger)实例,这个实例的根Logger就是在LogTest2中得到的rootLogger()
//2. 我们并没有在cd.itcast.log4j.Configure绑定的Logger上设置日志级别
//3. 他会去找他的父Logger的Level,如果没有继续向上找,直到找到rootLogger的Level,rootLogger必须设置Level,如果中途找到了设置了Level的父Logger,则使用该Logger的Level,且不再继续向上查找
//4. 因此打印出来就只有大于或等于INFO的日志级别信息了
private static Logger log = Logger.getLogger(Configure.class);

1.4 Log4J控制不同包下的类的日志级别也不同

1.4.1 代码

  1. LogicProcessor:与Configure放在不同包下
package cd.itcast.core;
import org.apache.log4j.Logger;
import cd.itcast.log4j.Configure;
public class LogicProcessor {
  private static Logger log=Logger.getLogger(LogicProcessor.class);

  public void init(Configure conf){
      log.info("init logic processor using conf");
  }

  public void process(){
      log.info("process some logic");
      log.debug("process some detail logic");
  }
}
  1. LogTest3:与LogicProcessor同包
package cd.itcast.log4j;
import org.apache.log4j.BasicConfigurator;
import org.junit.Test;
import cd.itcast.core.LogicProcessor;
public class LogTest3 {

  @Test
  public void testLog(){
      BasicConfigurator.configure();

      Configure conf=new Configure();
      conf.config();

      LogicProcessor processor=new LogicProcessor();
      processor.init(conf);
      processor.process();
  }
}
  1. 控制台输出:发现两个类中的日志都输出了
0 [main] INFO cd.itcast.log4j.Configure  - using default db.properties
0 [main] INFO cd.itcast.log4j.Configure  - using config file in classpath:db.properties
15 [main] DEBUG cd.itcast.log4j.Configure  - load properties file success
31 [main] DEBUG cd.itcast.log4j.Configure  - [properties] driverClass : com.mysql.jdbc.Driver
31 [main] DEBUG cd.itcast.log4j.Configure  - [properties] url : jdbc:mysql:///log4j
31 [main] DEBUG cd.itcast.log4j.Configure  - [properties] password : admin
31 [main] DEBUG cd.itcast.log4j.Configure  - [properties] username : log4j
31 [main] INFO cd.itcast.core.LogicProcessor  - init logic processor using conf
31 [main] INFO cd.itcast.core.LogicProcessor  - process some logic
31 [main] DEBUG cd.itcast.core.LogicProcessor  - process some detail logic
  1. 想cd.itcast.log.Configure做WARN级别之上的日志的输出,cd.itcast.core.LogicProcessor做DEBUG级别之上的日志输出
    1. 设置rootLogger日志级别为DEBUG;设置cd.itcast.log4j.Configure日志级别为WARN。
    2. 设置rootLogger日志级别为WARN;设置cd.itcast.core.LogicProcessor日志级别为DEBUG。
  2. LogTest3:第二种方法的具体实现
import org.junit.Test;
import cd.itcast.core.LogicProcessor;
public class LogTest3 {
  @Test
  public void testLog(){
      BasicConfigurator.configure();
      //rootLogger体系结构中的cd.itcast.log.Configure和cd.itcast.core.LogicProcessor默认日志级别都变成了WARN
      Logger.getRootLogger().setLevel(Level.WARN);
      //或者可以使用如下代码,表示将cd.itcast包下所有的类的日志级别改为Level.WARN,因为当我们绑定cd.itcast.core.LogicProcessor对应的Logger的时候,实际上隐式的绑定了cd、cd.itcast、cd.itcast.core这三个Logger
      //Logger.getLogger("cd.itcast").setLevel(Level.WARN);
      //通过Logger.getLogger(“cd.itcast.core.LogicProcessor”)得到的Logger实例和我们在LogicProcessor类中使用Logger.getLogger(LogicProcessor.class)得到的Logger实例是一个实例
      //即在一个rootLogger体系结构中,绑定到同一个名字的Logger实例只会有一份
      Logger.getLogger("cd.itcast.core.LogicProcessor").setLevel(Level.DEBUG);

      Configure conf=new Configure();
      conf.config();

      LogicProcessor processor=new LogicProcessor();
      processor.init(conf);
      processor.process();
  }
}
  1. 控制台输出
0 [main] INFO cd.itcast.core.LogicProcessor  - init logic processor using conf
0 [main] INFO cd.itcast.core.LogicProcessor  - process some logic
0 [main] DEBUG cd.itcast.core.LogicProcessor  - process some detail logic

1.5 Log4j体系结构

1.5.1 log4j三要素

  1. Logger:日志记录器
  2. Appender:什么地方
  3. Layout:什么格式

1.5.2 Logger的结构

1.5.2.1 创建Logger的本质
  1. Log4jEquals:
package cd.itcast.log4j;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;

public class Log4jEquals {
	public static void main(String[] args) {
		BasicConfigurator.configure();
	    Logger log1=Logger.getLogger("Log4jEquals");
	    Logger log2=Logger.getLogger("Log4jEquals");
	    //当我们说把一个日志记录器绑定在一个类上,这种说法是不准确的,正确的说,我们仅仅是使用给定的类的全限定名为Logger取了一个名字
	    Logger log3=Logger.getLogger(Log4jEquals.class);
	    Logger log4=Logger.getLogger("cd.itcast.log4j.Log4jEquals");
	    log1.info(log1==log2);
	    //log2使用的不是全限定名,所以对象不相等
	    log1.info(log2==log3);
	    log1.info(log3==log4);
	}
}	


  1. 控制台输出
0 [main] INFO Log4jEquals  - true
0 [main] INFO Log4jEquals  - false
0 [main] INFO Log4jEquals  - true
1.5.2.2 Logger的创建顺序及父子关系
//1. Logger的层次结构是按照Logger的名字来创建的,log1是log2的父Logger,log2为log3的父Logger
//2. 执行代码Logger.getLogger("cd.itcast.log")时,Log4J仅仅为我们创建了名为cd.itcast.log这个Logger,而不会自动创建其父Logger(即名为"cd.itcast"的Logger)
//3. 执行代码Logget.getLogger("cd.itcast")时,Log4J才会为我们创建名为"cd.itcast"这个Logger
//4. Log4J会自动的去寻找"cd.itcast"这个Logger的上下级关系,并自动的把这个新创建的Logger添加到已有的Logger结构体系中。
Logger log1=Logger.getLogger(“cd”);
Logger log2=Logger.getLogger(“cd.itcast”);
Logger log3=Logger.getLogger(“cd.itcast.log”);
1.5.2.3 rootLogger的特点
  1. rootLogger是没有名字的
  2. rootLogger是自动存在的
  3. rootLogger必须设置Level等级:默认值为Level.DEBUG
  4. rootLogger没有名字,所以无法像其他的类一样,可以通过Logger.getLogger(String)得到,他只能通过Logger.getRootLogger方法得到
1.5.2.4 Logger中方法
public class Logger {
    // 输出日志方法:
    public void debug(Object message);
    public void info(Object message);
    public void warn(Object message);
    public void error(Object message);
    public void fatal(Object message);
    // 输出带有错误r日志级别为DEBUG的日志方法:
    public void debug(Object message, Throwable t);
    public void info(Object message, Throwable t);
    public void warn(Object message, Throwable t);
    public void error(Object message, Throwable t);
    public void fatal(Object message, Throwable t);
    // 更通用的输出日志方法:
    public void log(Level p, Object message);
}
1.5.2.5 setThreshold限制日志输出:与setLevel方法的功能类似
  1. testLogLevel2
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

public class testLogLevel2 {
	public static void main(String[] args) {
	    //1. 系统先找最近的设置了Level的父Logger对应的Level等级,再找最近的设置了Threshold的父Logger对应的Threshold等级,哪个等级高以哪个为准
		BasicConfigurator.configure();
		Logger logger = Logger.getLogger("cd.itcast");
		//2. 使用logger.getLoggerRepository得到Logger栈,即从当前Logger开始其下的所有的子Logger。然后,我们设置了这个栈的日志门槛(Threshold),换句话说就是最低日志输出级别为INFO
	    logger.getLoggerRepository().setThreshold(Level.INFO);
	    logger.setLevel(Level.INFO);
	    Logger midLogger = Logger.getLogger("cd.itcast.log");
	    midLogger.getLoggerRepository().setThreshold(Level.DEBUG);
	    //3. midLogger最近设置了Level的父Logger为"cd.itcast",等级为INFO,其最近设置了Threshold的父Logger为"cd.itcast.log",等级为DEBUG,INFO>DEBUG,所以此时日志等级为INFO,所以只能打出info
	    midLogger.debug("debug");
	    midLogger.info("info");
	}
}

  1. 控制台输出
0 [main] INFO cd.itcast.log  - info

1.5.3 Appender的结构

Appender定义了日志输出的目的地

  1. testLogAppender1
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;

public class testLogAppender1 {
	public static void main(String[] args) {
		Logger log1=Logger.getLogger("cd");
	    log1.setLevel(Level.DEBUG);
	    //1. 把日志输出到控制台上的Appender,在创建ConsoleAppender的时候,需传入表示日志格式的类SimpleLayout(最简单的格式)的实例
	    log1.addAppender(new ConsoleAppender(new SimpleLayout()));
	    Logger log2=Logger.getLogger("cd.itcast.log");
	    //2. log2为log1的子Logger,它拥有log1的Appender,说明Appender与Level相同,拥有继承性
	    log2.info("log2 info");
	    log2.debug("log2 debug");
	}
}

  1. 控制台输出
INFO - log2 info
DEBUG - log2 debug
  1. testLogAppender1:改写
//在main方法最开始添加如下代码
BasicConfigurator.configure();
  1. 控制台输出:Logger会继承其所有父Logger上的Appender,不止一个
//继承"cd"这个Logger的Appender
INFO - log2 info
//继承rootLogger的Appender
0 [main] INFO cd.itcast.log  - log2 info
//同上
DEBUG - log2 debug
0 [main] DEBUG cd.itcast.log  - log2 debug
  1. testLogAppender2:setAdditivity(false)方法使该Logger的子Logger停止追加它以及它所有父Logger上的Appender
import java.io.IOException;

import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.SimpleLayout;

public class testLogAppender2 {
	public static void main(String[] args) throws IOException {
		BasicConfigurator.configure();
	    Logger log1=Logger.getLogger("cd");
	    log1.setAdditivity(false);
	    log1.addAppender(new ConsoleAppender(new SimpleLayout()));

	    Logger log2=Logger.getLogger("cd.itcast");
	    log2.addAppender(new FileAppender(new SimpleLayout(),"a0.log"));

	    Logger log3=Logger.getLogger("cd.itcast.log");
	    log3.info("log2 info");
	}
}
  1. 运行测试,结果:
//log2对应的a0.log文件中仍会打印,但rootLogger为log1的父Logger,所以其对应的控制台,就不会再打印了
INFO - log2 info

1.5.4 Layout的结构

创建Appender对象时需要传入Layout对象,它规定了日志格式

  1. testPatternLayout:PatternLayout使用标准的输出格式来指定格式化日志消息的样式
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

public class testPatternLayout {
	public static void main(String[] args) {
		Logger log=Logger.getLogger("cd");
		//先定义了一个格式化日志的模式
		//%r代表从Log4j启动到运行这条日志的时间差,单位为毫秒
		//%t代表运行该日志的线程名称(main,thread-1)不是类名
		//%-5p,首先-5代表这个字符总占用5个位置,p代表日志输出级别
		//%c代表输出日志的Logger的名字
		//%m代表输出的日志内容
		//%n代表分行
	    String pattern="%r [%t] %-5p %c - %m%n";
	    log.addAppender(new ConsoleAppender(new PatternLayout(pattern)));
	    Logger log2=Logger.getLogger("cd.itcast.log");
	    log2.info("log2 info");
	}
}
  1. 控制台输出
0 [main] INFO  cd.itcast.log - log2 info

1.6 Log4j配置文件详解

1.6.1 .properties配置文件

#配置rootLogger
#Level:debug
#Appender:三个,名分别为stdout、D、E,即rootLogger打印时,在这三个位置都会打印
#Logger.getRootLogger().setLevel(Level.DEBUG);
#Logger.getRootLogger().addAppender();
log4j.rootLogger = debug ,  stdout ,  D ,  E
#配置名为"cd.itcast.log4j"的Logger
#Level:debug
#Appender:D
#Logger.getLogger("cd.itcast.log4j").setLevel(Level.DEBUG);
#Logger.getLogger("cd.itcast.log4j").addAppender();
log4j.logger.cd.itcast.log4j = debug ,  D 
#关闭名为"cd.itcast.log4j"的Logger的Appender的追加性
#Logger.getLogger("cd.itcast.log4j").setAdditivity(false)
log4j.additivity.cd.itcast.log4j = false

#对名为"stdout"的Appender进行配置
#其Appender具体类为ConsoleAppender,即该Appender会被打印到控制台
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target = System.out
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c{1}:%L - %m%n

#对名为"D"的Appender进行配置
#其Appender具体类为DailyRollingFileAppender,即该Appender会被打印到指定文件,且该文件可以自动滚动
log4j.appender.D = org.apache.log4j.DailyRollingFileAppender
#日志打印到logs/log.log文件中
#也可以使用相对路径,为相对项目所在路径:D:\workspace\log4j1.2.17_test
#log4j.appender.D.File = logs/log.log会在D:\workspace\log4j1.2.17_test/logs/log.log建立日志
log4j.appender.D.File = D://logs/log.log
#默认值为true,表示追加,false表示覆盖原日志
log4j.appender.D.Append = true
#设置threshold
log4j.appender.D.Threshold = DEBUG
#设定Layout
log4j.appender.D.layout = org.apache.log4j.PatternLayout
log4j.appender.D.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

#对名为"E"的Appender进行配置
log4j.appender.E = org.apache.log4j.DailyRollingFileAppender
log4j.appender.E.File = D://logs/error.log
log4j.appender.E.Append = true
log4j.appender.E.Threshold = ERROR 
log4j.appender.E.layout = org.apache.log4j.PatternLayout
log4j.appender.E.layout.ConversionPattern = %-d{yyyy-MM-dd HH:mm:ss}  [ %t:%r ] - [ %p ]  %m%n

1.6.2 Appender具体实现类

  1. org.apache.log4j.ConsoleAppender:控制台
  2. org.apache.log4j.FileAppender:文件
  3. org.apache.log4j.DailyRollingFileAppender:每天产生一个日志文件
  4. org.apache.log4j.RollingFileAppender:文件大小到达指定尺寸的时候产生一个新的文件
  5. org.apache.log4j.WriterAppender:将日志信息以流格式发送到任意指定的地方

1.6.3 Layout具体实现类

  1. org.apache.log4j.HTMLLayout:以HTML表格形式布局
  2. org.apache.log4j.PatternLayout:可以灵活地指定布局模式
  3. org.apache.log4j.SimpleLayout:包含日志信息的级别和信息字符串
  4. org.apache.log4j.TTCCLayout:包含日志产生的时间、线程、类别等等信息

1.6.4 Layout具体实现类log4j.appender.E.layout.ConversionPattern后的特殊字符详解

%m   输出代码中指定的消息
%p   输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL 
%r   输出自应用启动到输出该log信息耗费的毫秒数 
%c   输出所属的类目,通常就是所在类的全名 
%t   输出产生该日志事件的线程名 
%n   输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n” 
%d   输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss , SSS},输出类似:2002年10月18日  22 : 10 : 28 , 921  
%l   输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java: 10 )

1.6.5 代码中初始化rootLogger的方式

//默认情况是先读取src同级的log4j.xml文件,如果获取不到则获取src内的log4j.properties文件
//在程序中调用BasicConfigurator.configure()方法:给根记录器增加一个ConsoleAppender,输出格式通过PatternLayout设为"%-4r [%t] %-5p %c %x - %m%n",还有根记录器的默认级别是Level.DEBUG.
BasicConfigurator.configure();
//读取使用Java的特性文件编写的配置文件
PropertyConfigurator.configure("D:/Code/conf/log4j.properties");
//读取指定XML形式的配置文件
DOMConfigurator.configure ( String filename )

1.6.6 .xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
	<appender class="org.apache.log4j.RollingFileAppender" name="zjjklog">
		<param name="maxFileSize" value="10000KB" />
		<param name="Threshold" value="ALL" />
		<param name="maxBackupIndex" value="5" />
		<param value="${fc.log.dir}/logs/fcrjdebug/zjjklog.txt" name="File" />
		<layout class="org.apache.log4j.PatternLayout">
			<param value="[${service.id}] %d %m%n" name="ConversionPattern" />
		</layout>
	</appender>
	<appender class="org.apache.log4j.DailyRollingFileAppender"
		name="fcrjtflog">
		<param value="'.'yyyy-MM-dd-HH" name="DatePattern" />
		<param name="Threshold" value="ALL" />
		<param value="${fc.log.dir}/logs/fcrjdebug/fcrjtflog.txt" name="File" />
		<layout class="org.apache.log4j.PatternLayout">
			<param value="[${service.id}]%d %t %p [%c] %m%n" name="ConversionPattern" />
		</layout>
	</appender>
	<appender class="org.apache.log4j.RollingFileAppender" name="fcrjdebuglog">
		<param name="maxFileSize" value="10000KB" />
		<param name="Threshold" value="ERROR" />
		<param name="maxBackupIndex" value="5" />
		<param value="${fc.log.dir}/logs/fcrjdebug/fcrjdebuglog.txt"
			name="File" />
		<layout class="org.apache.log4j.PatternLayout">
			<param value="[${service.id}]%d %t %p [%c] %F Line:[%L] %m%n"
				name="ConversionPattern" />
		</layout>
	</appender>

	<!-- category为logger的子类,现在已经不常使用,下面的category都可以用logger代替 -->
	<!-- Logger.getLogger("com.iflex.fcr").addAppender(); -->
	<category name="com.iflex.fcr">
		<appender-ref ref="fcrjdebuglog" />
	</category>
	<category name="1_BATCH_com.iflex.fcr" additivity="true">
		<appender-ref ref="fcrjdebuglog" />
	</category>
	<category name="1_com.iflex.fcr.alert" additivity="true">
		<appender-ref ref="fcrjdebuglog" />
	</category>
	<category name="mowaudit">
		<appender-ref ref="fcrjdebuglog" />
	</category>
	<category name="apiauditforjson">
		<appender-ref ref="fcrjdebuglog" />
	</category>
	<category name="org.apache.axis">
		<appender-ref ref="fcrjdebuglog" />
	</category>
	<category name="OUTBOUND_CALL_ADAPTER">
		<appender-ref ref="fcrjdebuglog" />
	</category>
	<category name="1_com.tf">
		<appender-ref ref="fcrjtflog" />
	</category>
	<category name="1_zjjk">
		<appender-ref ref="zjjklog" />
		<appender-ref ref="console" />
	</category>
	<category name="1_BATCH_zjjk">
		<appender-ref ref="zjjklog" />
		<appender-ref ref="console" />
	</category>
	<category name="1_BATCH_com.tf">
		<appender-ref ref="fcrjtflog" />
	</category>
	<logger additivity="false" name="PerfLogger">
		<appender-ref ref="fcrjdebuglog" />
	</logger>
	<logger name="org.eclipse.persistence">
		<level value="DEBUG" />
	</logger>
	<root>
		<priority value="OFF"></priority>
		<appender-ref ref="fcrjlog" />
	</root>
</log4j:configuration>

展开阅读全文

Windows版YOLOv4目标检测实战:训练自己的数据集

04-26
©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值