SpringBoot 入门(十)——日志

在一个项目的调试和后期维护中,日志是很重要的一部分,在 JavaWeb 中最有名的日志组件当属 log4j 了,但是在后来 Logback 貌似更厉害,SpringBoot 默认集成了 Logback,所以要在 SpringBoot 中使用 Logback 并不需要添加特别的依赖,如果有个性化需求,我们只需要修改配置文件即可。

一 打印日志

当我们启动一个 SpringBoot 项目的时候看到的那些打印其实就是 Logback 打印出来的,默认的日志级别是 info:

我们在之前的一个 HelloWorldController 中使用一下 Logger 来测试一下打印:

package com.qinshou.springbootdemo.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * Description:测试 Controller
 * Author: QinHao
 * Date: 2019/7/25 13:45
 */
@RequestMapping(value = "/")
@RestController
public class HelloWorldController {

    private final Logger mLogger = LoggerFactory.getLogger(this.getClass().getName());

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public Map<String, String> helloWorld() {
        mLogger.debug("访问了 HelloWorld 接口");
        mLogger.info("访问了 HelloWorld 接口");
        mLogger.warn("访问了 HelloWorld 接口");
        mLogger.error("访问了 HelloWorld 接口");
        Map<String, String> map = new HashMap<>();
        map.put("data", "Hello World");
        return map;
    }
}

我们在获取 Logger 对象时是通过 LoggerFactory 工厂类获取的,需要传递一个参数,这个参数相当于 Tag,这个 Tag 最好是指定为包名,这样对于后面指定特定的日志显示级别比较方便。

访问一下 localhost:8080 可以看到添加的日志打印成功打印出来了:

 

二 日志配置

在配置文件中我们可以设置日志的显示级别,通过 “logging.level.Tag 名=日志级别” 来设置:

# 设置 root 日志为 INFO 级别
logging.level.root=info
# 设置指定包名日志为 debug 级别
logging.level.com.qinshou.springbootdemo=error
# 日志输出文件
logging.file=log/qinshoublog-dev.log

重新运行一下项目访问一下 localhost:8080 ,可以看到只打印了 error 级别的日志:

除了可以在配置文件中配置,我们可以写一个 logback.xml 来统一配置级别,这个文件的基本写法如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
    <!-- SpringBoot 对 logback 日志的默认配置,参考 org.springframework.boot:spring-boot 依赖下 -->
    <!-- 的 org/springframework/boot/logging/logback/base.xml -->
    <include resource="org/springframework/boot/logging/logback/defaults.xml" />
    <property name="LOG_FILE"
        value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring.log}" />
    <include resource="org/springframework/boot/logging/logback/console-appender.xml" />

    <!-- <include resource="org/springframework/boot/logging/logback/file-appender.xml" /> -->
    <!-- 重写 SpringBoot 框架的 org/springframework/boot/logging/logback/file-appender.xml 的配置 -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <encoder>
            <pattern>${FILE_LOG_PATTERN}</pattern>
        </encoder>
        <file>${LOG_FILE}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_FILE}.%d{yyyy-MM-dd}.%i</fileNamePattern>
            <!-- 日志保留时间 -->
            <maxHistory>30</maxHistory>
            <!-- 每个日志达到 10MB 时会切分日志 -->
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>10MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>

    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="FILE" />
    </root>
</configuration>

这里面可以设置日志的切分大小,可以将大小先设置成了 10KB 来看看效果,多访问几次接口,就会看到日志分成了好几个文件:

 

三 面向切面记录日志

面向切面编程的思想我也不是很明白,但是利用 SpringBoot 的切面注解可以很方便的记录日志,这里记录一个例子:

package com.qinshou.springbootdemo.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;

import javax.servlet.http.HttpServletRequest;

/**
 * Description:TODO
 * Author:MrQinshou
 * Date:2018/9/19 20:38
 */
@Aspect
@Component
public class LogAspect {
    private final Logger mLogger = LoggerFactory.getLogger(this.getClass().getName());

    @Pointcut("execution(* com.qinshou.springbootdemo.controller.*.*(..))")
    public void log() {

    }

    /**
     * author:MrQinshou
     * Description:切面之前调用的方法
     * date:2018/9/19 20:42
     * param
     * return
     */
    @Before("log()")
    public void before(JoinPoint joinpoint) {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest httpServletRequest = servletRequestAttributes.getRequest();
        String url = httpServletRequest.getRequestURL().toString();
        String ip = httpServletRequest.getRemoteAddr();
        String classMethod = joinpoint.getSignature().getDeclaringTypeName() + "." + joinpoint.getSignature().getName();
        Object[] args = joinpoint.getArgs();
        RequestLog requestLog = new RequestLog(url, ip, classMethod, args);
        mLogger.info("Request--->{}", requestLog);
    }

    /**
     * author:MrQinshou
     * Description:切面之后调用的方法
     * date:2018/9/19 20:42
     * param
     * return
     */
    @After("log()")
    public void after() {
//        mLogger.info("after");
    }

    /**
     * author:MrQinshou
     * Description:捕获各个切面的返回值
     * date:2018/9/19 20:44
     * param
     * return
     */
    @AfterReturning(returning = "result", pointcut = "log()")
    public void afterReturn(Object result) {
        mLogger.info("afterReturn--->{}", result);
    }

    private class RequestLog {
        private String url;
        private String ip;
        private String classMethod;
        private Object[] args;

        public RequestLog(String url, String ip, String classMethod, Object[] args) {
            this.url = url;
            this.ip = ip;
            this.classMethod = classMethod;
            this.args = args;
        }

        @Override
        public String toString() {
            return "RequestLog{" +
                    "url='" + url + '\'' +
                    ", ip='" + ip + '\'' +
                    ", classMethod='" + classMethod + '\'' +
                    ", args=" + Arrays.toString(args) +
                    '}';
        }
    }
}

这样我们就可以在每个接口被访问时记录下日志了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值