1.src/resources路径下新建logback.xml
控制台彩色日志打印
info日志和异常日志分不同文件存储
每天自动生成日志
结合myibatis方便日志打印(debug模式)
converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
${CONSOLE_LOG_PATTERN}
utf8
${LOG_HOME}/category-server-log.%d{yyyy-MM-dd}.log
30
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
WARN
DENY
NEUTRAL
ERROR
DENY
NEUTRAL
${LOG_HOME}/category-server-error-log.%d{yyyy-MM-dd}.log
60
WARN
%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n
2.定义一个log实体 方便维护和后续的扩展
package com.wdcloud.categoryserver.log;
import com.wdcloud.categoryserver.common.entity.User;
public class LogEntity {
private long id;
private String url;
private String ip;
private String httpMethod;
private String classMethod;
private String args;
private String reqParams;
private String respParams;
private long spendTime;
private String logType;
private User user;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getHttpMethod() {
return httpMethod;
}
public void setHttpMethod(String httpMethod) {
this.httpMethod = httpMethod;
}
public String getClassMethod() {
return classMethod;
}
public void setClassMethod(String classMethod) {
this.classMethod = classMethod;
}
public String getArgs() {
return args;
}
public void setArgs(String args) {
this.args = args;
}
public String getReqParams() {
return reqParams;
}
public void setReqParams(String reqParams) {
this.reqParams = reqParams;
}
public String getRespParams() {
return respParams;
}
public void setRespParams(String respParams) {
this.respParams = respParams;
}
public long getSpendTime() {
return spendTime;
}
public void setSpendTime(long spendTime) {
this.spendTime = spendTime;
}
public String getLogType() {
return logType;
}
public void setLogType(String logType) {
this.logType = logType;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
3.定义一个controller 的切面
package com.wdcloud.categoryserver.log;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wdcloud.categoryserver.common.constant.AppConstants;
import com.wdcloud.categoryserver.utils.AppUtil;
import com.wdcloud.categoryserver.utils.JsonUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Aspect
@Component
@Order(1)
public class ControllerLogAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
ThreadLocal startTime = new ThreadLocal<>();
ThreadLocal webLogThreadLocal = new ThreadLocal<>();
@Pointcut("execution(* com.wdcloud.categoryserver.business.*.controller.*.*(..))")
public void serviceAspect() {
}
@Before("serviceAspect()")
public void doBefore(JoinPoint joinPoint) {
// 接收到请求,记录请求内容
startTime.set(System.currentTimeMillis());
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
webLogThreadLocal.set(new LogEntity());
webLogThreadLocal.get().setHttpMethod(request.getMethod());
webLogThreadLocal.get().setClassMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
webLogThreadLocal.get().setUrl(request.getRequestURL().toString());
webLogThreadLocal.get().setIp(request.getRemoteAddr());
webLogThreadLocal.get().setArgs(AppUtil.getArgs(joinPoint));
webLogThreadLocal.get().setLogType(AppConstants.LOG_TYPE_HTTP);
webLogThreadLocal.get().setReqParams(JsonUtil.objectToJson(request.getParameterMap()));
webLogThreadLocal.get().setUser(AppUtil.getUser(request));
}
@AfterReturning(returning = "result", pointcut = "serviceAspect()")
public void doAfterReturning(Object result) {
// 处理完请求,返回内容
ObjectMapper mapper = new ObjectMapper();
try {
webLogThreadLocal.get().setRespParams(mapper.writeValueAsString(result));
} catch (JsonProcessingException e) {
logger.error(AppUtil.getExceptionDetail(e));
}
webLogThreadLocal.get().setSpendTime(System.currentTimeMillis() - startTime.get());
try {
logger.info(">>>"+mapper.writeValueAsString(webLogThreadLocal.get()));
} catch (JsonProcessingException e) {
logger.error(AppUtil.getExceptionDetail(e));
}
}
}
4.定义一个供dubbo调用的service切面
package com.wdcloud.categoryserver.log;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.wdcloud.categoryserver.common.constant.AppConstants;
import com.wdcloud.categoryserver.utils.AppUtil;
import com.wdcloud.categoryserver.utils.JsonUtil;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
@Aspect
@Component
@Order(1)
public class ServiceLogAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
ThreadLocal startTime = new ThreadLocal<>();
ThreadLocal webLogThreadLocal = new ThreadLocal<>();
@Pointcut("execution(* com.wdcloud.categoryserver.front.*.service.*.*(..))")
public void serviceAspect() {
}
@Before("serviceAspect()")
public void doBefore(JoinPoint joinPoint) {
// 接收到请求,记录请求内容
startTime.set(System.currentTimeMillis());
webLogThreadLocal.set(new LogEntity());
webLogThreadLocal.get().setClassMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
webLogThreadLocal.get().setArgs(AppUtil.getArgs(joinPoint));
webLogThreadLocal.get().setLogType(AppConstants.LOG_TYPE_DUBBO);
}
@AfterReturning(returning = "result", pointcut = "serviceAspect()")
public void doAfterReturning(Object result) {
// 处理完请求,返回内容
ObjectMapper mapper = new ObjectMapper();
try {
webLogThreadLocal.get().setRespParams(mapper.writeValueAsString(result));
} catch (JsonProcessingException e) {
logger.error(AppUtil.getExceptionDetail(e));
}
webLogThreadLocal.get().setSpendTime(System.currentTimeMillis() - startTime.get());
try {
logger.info(">>>"+mapper.writeValueAsString(webLogThreadLocal.get()));
} catch (JsonProcessingException e) {
logger.error(AppUtil.getExceptionDetail(e));
}
}
}
5.统一异常处理
package com.wdcloud.categoryserver.common.exception;
import com.wdcloud.categoryserver.common.constant.AppConstants;
import com.wdcloud.categoryserver.common.constant.CodeConstants;
import com.wdcloud.categoryserver.common.entity.BaseView;
import com.wdcloud.categoryserver.log.LogEntity;
import com.wdcloud.categoryserver.utils.AppUtil;
import com.wdcloud.categoryserver.utils.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.support.MissingServletRequestPartException;
import javax.servlet.http.HttpServletRequest;
@ControllerAdvice(annotations = {RestController.class})
public class GlobalExceptionHandler {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@ExceptionHandler(value = Exception.class)
@ResponseBody
public BaseView defaultErrorHandler(HttpServletRequest request, Exception e) throws Exception {
BaseView baseView = new BaseView(CodeConstants.SYSTEM_EXCEPTION,CodeConstants.SYSTEM_EXCEPTION_MSG);
printLog(request,e,baseView);
return baseView;
}
@ExceptionHandler(value = {HttpMessageNotReadableException.class, MissingServletRequestPartException.class ,MissingServletRequestParameterException.class, MultipartException.class})
@ResponseBody
public BaseView httpMessageNotReadableExceptionErrorHandler(HttpServletRequest request, Exception e) throws Exception {
BaseView baseView = new BaseView(CodeConstants.PARAMETER_ERROR,CodeConstants.PARAMETER_ERROR_MSG);
printLog(request,e,baseView);
return baseView;
}
@ExceptionHandler(value = {HttpMediaTypeNotSupportedException.class})
@ResponseBody
public BaseView httpMediaTypeNotSupportedExceptionHandler(HttpServletRequest request, Exception e) throws Exception {
BaseView baseView = new BaseView(CodeConstants.CONTENTTYPE_ERROR,CodeConstants.CONTENTTYPE_ERROR_MSG);
printLog(request,e,baseView);
return baseView;
}
private void printLog(HttpServletRequest request,Exception e,BaseView baseView){
logger.error(AppUtil.getExceptionDetail(e));
LogEntity logEntity = new LogEntity();
logEntity.setHttpMethod(request.getMethod());
logEntity.setUrl(request.getRequestURL().toString());
logEntity.setIp(request.getRemoteAddr());
logEntity.setArgs(AppUtil.getRequestBody(request));
logEntity.setLogType(AppConstants.LOG_TYPE_HTTP);
logEntity.setReqParams(JsonUtil.objectToJson(request.getParameterMap()));
logEntity.setRespParams(JsonUtil.objectToJson(baseView));
logger.error(">>>"+JsonUtil.objectToJson(logEntity));
}
}



