实战SSM_O2O商铺_06logback配置与使用

文章目录

  • 日志概述
    • logging
    • log4j
    • commons-logging
    • slf4j
    • logback
    • 日志框架总结
  • Maven依赖
  • logback加载配置文件规则
  • logback 日志级别
  • 配置
  • 测试
  • Github地址
在这里插入图片描述

日志概述

log4j、Logging、commons-logging、slf4j、logback,都耳熟能详吧,那么具体的区别和联系呢,我们这里借o2o这个小项目的机会梳理一下。

logging

Java 自带的日志工具类,在 JDK 1.5 开始就已经有了,在 java.util.logging 包下。


log4j

Log4j 是 Apache 的一个开源日志框架,也是市场占有率最多的一个框架,log4j 在 2015/08/05 Apache 宣布停止维护了,用户需要切换到 Log4j2上面去。


commons-logging

log4j 是一个具体的日志框架的实现,而 commons-logging 就是日志的门面接口,它也是 apache 最早提供的日志门面接口,用户可以根据喜好选择不同的日志实现框架,而不必改动日志定义,这就是日志门面的好处,符合面对接口抽象编程。


slf4j

全称:Simple Logging Facade for Java,即简单日志门面接口,和 Apache 的 commons-logging 是一样的概念,它们都不是具体的日志框架,你可以指定其他主流的日志实现框架。

Slf4j 也是现在主流的日志门面框架,使用 Slf4j 可以很灵活的使用占位符进行参数占位,简化代码,拥有更好的可读性。


logback

Logback 是 Slf4j 的原生实现框架,同样也是出自 Log4j 一个人之手,但拥有比 log4j 更多的优点、特性和更做强的性能,现在基本都用来代替 log4j 成为主流。


日志框架总结

  • commons-logging、slf4j 只是一种日志抽象门面,不是具体的日志框架。
  • log4j、logback 是具体的日志实现框架。
  • 一般首选强烈推荐使用 slf4j + logback。当然也可以使用slf4j + log4j、commons-logging +log4j 这两种日志组合框架。

一般情况下,Logback与slf4J组合使用。

logback的官方网站:http://logback.qos.ch

SLF4J的官方网站:http://www.slf4j.org

这里写图片描述

看出 slf4j 很强大,不但能和各种日志框架对接,还能和日志门面 commons-logging 进行融合。


logback的三个模块

  • logback-core
  • logback-classic
  • logback-access

logback-core是logback-classic和logback-access模块的基础模块。logback-classic是log4j的一个改良版本,均出自同一个作者之手。


Maven依赖

代码语言:javascript
复制
<dependency>
	<groupId>ch.qos.logbackgroupId>
	<artifactId>logback-classicartifactId>
	<version>1.2.1version>
dependency>
这里写图片描述

logback加载配置文件规则

1. 在 classpath 中寻找 logback-test.xml文件

2. 如果找不到 logback-test.xml,则在 classpath 中寻找 logback.groovy 文件

3. 如果找不到 logback.groovy,则在 classpath 中寻找 logback.xml文件

4. 如果上述的文件都找不到,则 logback 会使用 JDK 的 SPI 机制查找 META-INF/services/ch.qos.logback.classic.spi.Configurator 中的 logback 配置实现类,这个实现类必须实现 Configuration 接口,使用它的实现来进行配置

5. 如果上述操作都不成功,logback 就会使用它自带的 BasicConfigurator 来配置,并将日志输出到 console


logback 日志级别

TRACE < DEBUG < INFO < WARN < ERROR


配置

代码语言:javascript
复制
<configuration scan="true" scanPeriod="60 seconds" debug="false">
&lt;property name=&#34;app.name&#34; value=&#34;o2o&#34; /&gt; 
&lt;property name=&#34;log.level&#34; value=&#34;DEBUG&#34;/&gt;
&lt;property name=&#34;log.maxHistory&#34; value=&#34;30&#34;/&gt;

&lt;property name=&#34;log.filePath&#34; value=&#34;D:/logs/${app.name}&#34;/&gt;

&lt;property name=&#34;log.pattern&#34; value=&#34;%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n&#34;/&gt;



&lt;contextName&gt;${app.name}contextName&gt; 




&lt;appender name=&#34;consoleAppender&#34; class=&#34;ch.qos.logback.core.ConsoleAppender&#34;&gt;
	
	&lt;encoder class=&#34;ch.qos.logback.classic.encoder.PatternLayoutEncoder&#34;&gt;
		&lt;patten&gt;${log.pattern}patten&gt;
	encoder&gt;
appender&gt;



&lt;appender name=&#34;debugAppender&#34;
	class=&#34;ch.qos.logback.core.rolling.RollingFileAppender&#34;&gt;
	
	&lt;file&gt;${log.filePath}/debug.logfile&gt;
	
	&lt;append&gt;trueappend&gt;
	
	
	&lt;rollingPolicy class=&#34;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&#34;&gt;
		&lt;fileNamePattern&gt;${log.filePath}/debug/debug.%d{yyyy-MM-dd}.%i.log.zip
		fileNamePattern&gt;
		
		&lt;maxHistory&gt;${log.maxHistory}maxHistory&gt;
		
		&lt;timeBasedFileNamingAndTriggeringPolicy
			class=&#34;ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP&#34;&gt;
			&lt;maxFileSize&gt;1MBmaxFileSize&gt;
		timeBasedFileNamingAndTriggeringPolicy&gt;
	rollingPolicy&gt;
	
	
	&lt;encoder class=&#34;ch.qos.logback.classic.encoder.PatternLayoutEncoder&#34;&gt;
		&lt;pattern&gt;${log.pattern}pattern&gt;
	encoder&gt;
	
	&lt;filter class=&#34;ch.qos.logback.classic.filter.LevelFilter&#34;&gt;   
 		 &lt;level&gt;DEBUGlevel&gt;   
		 &lt;onMatch&gt;ACCEPTonMatch&gt;   
 		 &lt;onMismatch&gt;DENYonMismatch&gt;   
	filter&gt;  
appender&gt;



&lt;appender name=&#34;infoAppender&#34;
	class=&#34;ch.qos.logback.core.rolling.RollingFileAppender&#34;&gt;
	
	&lt;file&gt;${log.filePath}/info.logfile&gt;
	
	&lt;append&gt;trueappend&gt;
	
	
	&lt;rollingPolicy class=&#34;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&#34;&gt;
		&lt;fileNamePattern&gt;${log.filePath}/info/info.%d{yyyy-MM-dd}.%i.log.zip
		fileNamePattern&gt;
		
		&lt;maxHistory&gt;${log.maxHistory}maxHistory&gt;
		
		&lt;timeBasedFileNamingAndTriggeringPolicy
			class=&#34;ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP&#34;&gt;
			&lt;maxFileSize&gt;1MBmaxFileSize&gt;
		timeBasedFileNamingAndTriggeringPolicy&gt;
	rollingPolicy&gt;
	
	
	&lt;encoder class=&#34;ch.qos.logback.classic.encoder.PatternLayoutEncoder&#34;&gt;
		&lt;pattern&gt;${log.pattern}pattern&gt;
	encoder&gt;
	
	&lt;filter class=&#34;ch.qos.logback.classic.filter.LevelFilter&#34;&gt;
		&lt;level&gt;INFOlevel&gt;
		&lt;onMatch&gt;ACCEPTonMatch&gt;
		&lt;onMismatch&gt;DENYonMismatch&gt;
	filter&gt;
appender&gt;


&lt;appender name=&#34;errorAppender&#34;
	class=&#34;ch.qos.logback.core.rolling.RollingFileAppender&#34;&gt;
	
	&lt;file&gt;${log.filePath}/error.logfile&gt;
	
	&lt;append&gt;trueappend&gt;
	
	
	&lt;rollingPolicy class=&#34;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&#34;&gt;
		&lt;fileNamePattern&gt;${log.filePath}/error/error.%d{yyyy-MM-dd}.%i.log.zip
		fileNamePattern&gt;
		
		&lt;maxHistory&gt;${log.maxHistory}maxHistory&gt;
		
		&lt;timeBasedFileNamingAndTriggeringPolicy
			class=&#34;ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP&#34;&gt;
			&lt;maxFileSize&gt;1MBmaxFileSize&gt;
		timeBasedFileNamingAndTriggeringPolicy&gt;
	rollingPolicy&gt;
	
	
	&lt;encoder class=&#34;ch.qos.logback.classic.encoder.PatternLayoutEncoder&#34;&gt;
		&lt;pattern&gt;${log.pattern}pattern&gt;
	encoder&gt;
	
	&lt;filter class=&#34;ch.qos.logback.classic.filter.LevelFilter&#34;&gt;
		&lt;level&gt;ERRORlevel&gt;
		&lt;onMatch&gt;ACCEPTonMatch&gt;
		&lt;onMismatch&gt;DENYonMismatch&gt;
	filter&gt;
appender&gt;

 
&lt;logger name=&#34;com.artisan.o2o&#34; level=&#34;${log.level}&#34; additivity=&#34;true&#34;&gt;
	&lt;appender-ref ref=&#34;debugAppender&#34; /&gt;
	&lt;appender-ref ref=&#34;infoAppender&#34; /&gt;
	&lt;appender-ref ref=&#34;errorAppender&#34; /&gt;
logger&gt;


&lt;root level=&#34;${log.level}&#34;&gt;
	&lt;appender-ref ref=&#34;consoleAppender&#34; /&gt;
root&gt;

configuration>


测试

我们在AreaController中加些log输出

代码语言:javascript
复制
package com.artisan.o2o.web;

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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.artisan.o2o.entity.Area;
import com.artisan.o2o.service.AreaService;

@Controller
@RequestMapping("/superadmin")
public class AreaController {
Logger logger = LoggerFactory.getLogger(AreaController.class);

@Autowired
AreaService areaService;

@RequestMapping(value = &#34;/listArea&#34;, method = RequestMethod.GET)
@ResponseBody
public Map&lt;String, Object&gt; getAreas() {
	logger.info(&#34;-----begin getAreas------&#34;);
	Long beginTimeLong = System.currentTimeMillis();

	Map&lt;String, Object&gt; map = new HashMap&lt;String, Object&gt;();
	List&lt;Area&gt; areaList = new ArrayList&lt;Area&gt;();
	try {
		areaList = areaService.getAreaList();
		map.put(&#34;total&#34;, areaList.size());
		map.put(&#34;rows&#34;, areaList);

		for (Area area : areaList) {
			System.out.println(&#34;区域:&#34; + area);
		}
	} catch (Exception e) {
		e.printStackTrace();
		map.put(&#34;success&#34;, false);
		map.put(&#34;errMsg&#34;, e.getMessage().toString());
		logger.error(&#34;exception happpens , desc [{}] &#34;, e.getMessage());
	}


	Long endTimeLong = System.currentTimeMillis();
	logger.debug(&#34;cost [{}ms]&#34;, endTimeLong - beginTimeLong);
	logger.info(&#34;-----end getAreas------&#34;);
	return map;
}

}

启动服务,测试

这里写图片描述
这里写图片描述

rollingPolicy的配置

这里写图片描述

接下来,我们将AreaDao.xml中 id为 queryArea的statement sql 中的area_name 改成area_name1,因为数据库tb_area表没有该字段,验证下,error的配置项。

这里写图片描述

同时 http://localhost:8080/o2o/superadmin/listArea

这里写图片描述

这里将不同级别的日志分别打印到了不同的文件中,日志的配置可以灵活配置,这里仅仅是阐述用法,日志的记录方式后续会调整。


Github地址

代码地址: https://github.com/yangshangwei/o2o