您好,欢迎来到年旅网。
搜索
您的当前位置:首页Springboot实战

Springboot实战

来源:年旅网

logback日志配置模板

<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds">
    <property name="LOG_HOME" value="./logs"/>
    <property name="FORMAT" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36}-%L- %msg%n"/>
    <property name="RollingMaxHistory" value="30"/>
    <property name="RollingFileNamePattern" value="${LOG_HOME}/%d{yyyy-MM-dd}"/>

    <!-- 控制台彩色日志格式 -->
    <property name="CONSOLE_LOG_PATTERN" value="%red(%d{yyyy-MM-dd HH:mm:ss})|%highlight(%-5level)|%green(%thread)|%boldMagenta(%logger{36}-%L)|(%msg%n)" />
    
    <!-- 控制台输出 -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
            <charset>utf8</charset>
        </encoder>
    </appender>

    <!-- 生成DEBUG日志文件 -->
    <appender name="DEBUG-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${RollingFileNamePattern}/debug/%d{yyyy-MM-dd}.%i-debug.log</FileNamePattern>
            <!--日志文件最大的大小-->
            <maxFileSize>500MB</maxFileSize>
            <!--日志文件保留天数-->
            <MaxHistory>${RollingMaxHistory}</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>${FORMAT}</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>DEBUG</level>
        </filter>
    </appender>

    <!-- 生成INFO日志文件 -->
    <appender name="INFO-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${RollingFileNamePattern}/info/%d{yyyy-MM-dd}.%i-info.log</FileNamePattern>
            <!--日志文件最大的大小-->
            <maxFileSize>500MB</maxFileSize>
            <!--日志文件保留天数-->
            <MaxHistory>${RollingMaxHistory}</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>${FORMAT}</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>INFO</level>
        </filter>
    </appender>

    <!-- 生成ERROR日志文件 -->
    <appender name="ERROR-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!--日志文件输出的文件名-->
            <FileNamePattern>${RollingFileNamePattern}/error/%d{yyyy-MM-dd}.%i-error.log</FileNamePattern>
            <!--日志文件最大的大小-->
            <maxFileSize>500MB</maxFileSize>
            <!--日志文件保留天数-->
            <MaxHistory>${RollingMaxHistory}</MaxHistory>
        </rollingPolicy>
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
            <pattern>${FORMAT}</pattern>
        </encoder>
        <!-- 打印日志级别 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
    </appender>

	<!--分环境配置-->
    <springProfile name="sit,test,dev">
        <root level="debug">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="DEBUG-FILE"/>
            <appender-ref ref="INFO-FILE"/>
            <appender-ref ref="ERROR-FILE"/>
        </root>
    </springProfile>
    <springProfile name="prod">
        <root level="info">
            <appender-ref ref="STDOUT"/>
            <appender-ref ref="DEBUG-FILE"/>
            <appender-ref ref="INFO-FILE"/>
            <appender-ref ref="ERROR-FILE"/>
        </root>
    </springProfile>


    <!--此配置优先级 appender>logger>root-->
    <logger name="org.springframework" level="INFO"/>
    <logger name="org.apache" level="INFO"/>
    <logger name="com.netflix" level="INFO"/>

</configuration>

前后端时间格式转换

前端传递utc时间格式,前端展示规范时间格式,可以通过注解完成


VO(返回前端时间时):
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")

接口统一日志处理

利用aop统一拦截接口,输出日志

package com.crc.common.aop;

import com.crc.common.bean.BaseResBean;
import com.crc.common.define.CommonDefine;
import com.crc.common.utils.JWTTokenUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
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.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Objects;

/**
 * 日志切面
 */
@Slf4j
@Component
@Aspect
public class LogAspect {

    @Pointcut("@within(org.springframework.web.bind.annotation.RestController) && execution(* com.crc.admin..controller..*.*(..))")
    public void pointCut() {
    }

    @Before("pointCut()")
    public void doBefore(JoinPoint joinPoint) throws JsonProcessingException {
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        log.info("请求开始 {},url:{},---header:{}--- req:{}",
                getApiOperationStr(joinPoint),
                request.getRequestURI(),
                getHeader(request),
                getReq(request, joinPoint));
    }

    @AfterReturning(pointcut = "pointCut()", returning = "returnValue")
    public void releaseResource(BaseResBean returnValue) throws JsonProcessingException {
        log.info("请求结束res:{}", new ObjectMapper().writeValueAsString(returnValue));
    }

    private String getApiOperationStr(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        ApiOperation manageLogin = method.getAnnotation(ApiOperation.class);
        if (manageLogin == null) {
            return "";
        }
        return manageLogin.value();
    }

    private String getReq(HttpServletRequest request, JoinPoint joinPoint) throws JsonProcessingException {
        if ("GET".equals(request.getMethod())) {
            return new ObjectMapper().writeValueAsString(request.getParameterMap());
        }
        return Arrays.toString(joinPoint.getArgs());
    }

    private String getHeader(HttpServletRequest request) {
        String token = request.getHeader(CommonDefine.TOKEN_NAME);
        return String.format("{account:%s,token:%s}",JWTTokenUtil.getUseridByFullJWTToken(token),token);
    }
}

统一接口参数校验

加入spring容器管理即可生效

package com.crc.common.config;

import com.crc.common.bean.BaseResBean;
import com.crc.common.define.CrcErrorCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * 全局异常捕获
 */
@Slf4j
@RestControllerAdvice
public class CrcServerExceptionHandler {

    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public BaseResBean resolveException(MethodArgumentNotValidException exception) {
        BindingResult bindingResult = exception.getBindingResult();
        FieldError fieldError = bindingResult.getFieldError();
        if (fieldError == null) {
            return CrcErrorCodeEnum.PARAM_IS_NULL.toReturnValue();
        }
        return CrcErrorCodeEnum.PARAM_IS_NULL.error(fieldError.getDefaultMessage());
    }

}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务