<?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
本站由北京市万商天勤律师事务所王兴未律师提供法律服务