# SpringMVC集成Log4j2

之前大部分的项目都使用log4j打印管理日志，但是最新的spring4.0+已经不建议使用了，建议使用log4j2，是log4j的升级版本。定义了下面几种日志级别：

**trace\<debug\<info\<warn\<error\<fatal**

配置log4j2很简单。

## 1. 配置pom依赖

```markup
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.7</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-jcl</artifactId>
    <version>2.7</version>
</dependency>
```

## 2. 配置log4j2.xml

在resources下新建log4j2.xml，会被自动读取，不需要再web.xml配置。配置示例如下：

```markup
<?xml version="1.0" encoding="UTF-8"?>
<!-- Configuration后面的status，这个用于设置log4j2自身内部的信息输出，可以不设置，当设置成trace时，你会看到log4j2内部各种详细输出。 -->
<Configuration status="WARN">
    <!-- Properties：配置一些变量，可以再后面引用 -->
    <Properties>
        <Property name="business">../mylogs/business.log</Property>
        <Property name="all">../mylogs/all.log</Property>
    </Properties>

    <!-- Appenders：配置日志输出的方式 -->
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout
                pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
        </Console>
        <!-- append="false"表示每次重启容器会自动清空 -->
        <File name="Business" fileName="${business}" append="true">
            <PatternLayout
                pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%n" />
        </File>
        <File name="All" fileName="${all}" append="true">
            <PatternLayout
                pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%n" />
        </File>
    </Appenders>

    <!-- Loggers：配置日志输出策略，additivity="false"不会输出到root -->
    <Loggers>
        <Logger name="org.springframework.beans.factory" level="ERROR" additivity="false">
            <AppenderRef ref="Console" />
        </Logger>
        <Logger name="com.timeline" level="DEBUG">
            <AppenderRef ref="Business" />
        </Logger>
        <!-- 设置指定类的日志输出，如果设置级别为info，即使root的级别为error，指定类的info级别以上的仍能输出，相当于重写了root。 -->
        <Root level="error">
            <AppenderRef ref="All" />
        </Root>
    </Loggers>
</Configuration>
```

## 3. 在java文件中使用

```java
private static final Logger logger = LogManager.getLogger(CalalogController.class);
...
logger.debug("controller-addCatalog-req:" + catalog.toString());
...
```

## 4. 查看效果

重启tomcat后，触发到方法运行，就会在${tomcat\_home}/mylogs文件夹下面出现`all.log`和`business.log`，里面就是我们打印的日志。

## 5. 日志输出格式说明

参考我们上面的配置：

```
%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%n
```

解释一下每个字段的意思：

```
%d 打印日期，后面可以指定格式，比如：%d{yyyy-MM-dd HH:mm:ss.SSS}。默认是ISO8601。
%-5level(或者%p) %level是打印日志级别，加了-5就表示若level名字长度小于5右边用空格填充。
%class{36}(或者%C)  %class打印class名，加了{36}表示类名最长36个节点，超出的从右向左截取36节点，比如com.example.test属于3个节点长度
%L 显示调用logger代码行
%M 显示调用logger的方法名
%msg(或者%m) 显示logger打印的日志
%n 换行
```

其他比较实用的：

```
%l 输出日志事件的发生位置，包括类名、方法名，以及在代码中的行数
%t 输出线程名
%r 显示从程序启动到该条日志打印已经经过的毫秒数
%F 显示调用logger的源文件名
%% 显示一个百分号
```

个人比较喜欢的格式：

```
%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %l %t [msg]%m%n
```

## 6. 注意事项

### 6.1 什么时候该用isDebugEnabled判断

我们在项目中经常看到这样的代码：

```java
if (logger.isDebugEnabled()) {

    logger.debug(message);

}
```

其实加不加这个判断效果是一样的，但是这个判断的作用是为了提高性能，比如下面的代码，有的时候我们传入的入参需要一定的系统开销，如果不加判断的话，debug的参数也会传入，只是在内部逻辑决定要不要打印出来，但是这就需要计算入参了，在高并发的系统中会严重浪费系统资源。所以建议如果dbeug的入参不需要计算直接写logger.debug()就可以，如果 入参需要计算，就最好加上isDebugEnabled的判断。

```java
if (logger.isDebugEnabled()) {

    logger.debug(getMessage());

}
```

> 参考：
>
> <https://www.cnblogs.com/hafiz/p/6170702.html>
>
> <http://blog.51cto.com/netpeak/1897216>
>
> <http://www.cnblogs.com/yudar/p/5113655.html>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://jun-wang.gitbook.io/learnjava/ji-shu-xue-xi/spring/springmvc-ji-cheng-log4j2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
