mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-11 16:57:14 +08:00
refactor(log): 优化日志模块
This commit is contained in:
@@ -26,7 +26,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
import top.continew.starter.log.autoconfigure.LogProperties;
|
import top.continew.starter.log.model.LogProperties;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@@ -51,42 +51,42 @@ public class AccessLogAspect {
|
|||||||
/**
|
/**
|
||||||
* 切点 - 匹配所有控制器层的 GET 请求方法
|
* 切点 - 匹配所有控制器层的 GET 请求方法
|
||||||
*/
|
*/
|
||||||
@Pointcut("within(@org.springframework.web.bind.annotation.RequestMapping *)")
|
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
|
||||||
public void pointcut() {
|
public void pointcut() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切点 - 匹配所有控制器层的 GET 请求方法
|
* 切点 - 匹配所有控制器层的 GET 请求方法
|
||||||
*/
|
*/
|
||||||
@Pointcut("within(@org.springframework.web.bind.annotation.GetMapping *)")
|
@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
|
||||||
public void pointcutGet() {
|
public void pointcutGet() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切点 - 匹配所有控制器层的 POST 请求方法
|
* 切点 - 匹配所有控制器层的 POST 请求方法
|
||||||
*/
|
*/
|
||||||
@Pointcut("within(@org.springframework.web.bind.annotation.PostMapping *)")
|
@Pointcut("@annotation(org.springframework.web.bind.annotation.PostMapping)")
|
||||||
public void pointcutPost() {
|
public void pointcutPost() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切点 - 匹配所有控制器层的 PUT 请求方法
|
* 切点 - 匹配所有控制器层的 PUT 请求方法
|
||||||
*/
|
*/
|
||||||
@Pointcut("within(@org.springframework.web.bind.annotation.PutMapping *)")
|
@Pointcut("@annotation(org.springframework.web.bind.annotation.PutMapping)")
|
||||||
public void pointcutPut() {
|
public void pointcutPut() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切点 - 匹配所有控制器层的 DELETE 请求方法
|
* 切点 - 匹配所有控制器层的 DELETE 请求方法
|
||||||
*/
|
*/
|
||||||
@Pointcut("within(@org.springframework.web.bind.annotation.DeleteMapping *)")
|
@Pointcut("@annotation(org.springframework.web.bind.annotation.DeleteMapping)")
|
||||||
public void pointcutDelete() {
|
public void pointcutDelete() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 切点 - 匹配所有控制器层的 PATCH 请求方法
|
* 切点 - 匹配所有控制器层的 PATCH 请求方法
|
||||||
*/
|
*/
|
||||||
@Pointcut("within(@org.springframework.web.bind.annotation.PatchMapping *)")
|
@Pointcut("@annotation(org.springframework.web.bind.annotation.PatchMapping)")
|
||||||
public void pointcutPatch() {
|
public void pointcutPatch() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package top.continew.starter.log.aspect;
|
package top.continew.starter.log.aspect;
|
||||||
|
|
||||||
|
import cn.hutool.core.annotation.AnnotationUtil;
|
||||||
import cn.hutool.core.text.CharSequenceUtil;
|
import cn.hutool.core.text.CharSequenceUtil;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
@@ -30,10 +31,11 @@ import org.slf4j.LoggerFactory;
|
|||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
import top.continew.starter.log.annotation.Log;
|
import top.continew.starter.log.annotation.Log;
|
||||||
import top.continew.starter.log.autoconfigure.LogProperties;
|
|
||||||
import top.continew.starter.log.dao.LogDao;
|
import top.continew.starter.log.dao.LogDao;
|
||||||
import top.continew.starter.log.handler.LogHandler;
|
import top.continew.starter.log.handler.LogHandler;
|
||||||
|
import top.continew.starter.log.model.LogProperties;
|
||||||
import top.continew.starter.log.model.LogRecord;
|
import top.continew.starter.log.model.LogRecord;
|
||||||
|
import top.continew.starter.web.util.SpringWebUtils;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
@@ -76,13 +78,13 @@ public class LogAspect {
|
|||||||
@Around("pointcut()")
|
@Around("pointcut()")
|
||||||
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
Instant startTime = Instant.now();
|
Instant startTime = Instant.now();
|
||||||
// 非 Web 环境不记录
|
// 指定规则不记录
|
||||||
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
|
HttpServletRequest request = SpringWebUtils.getRequest();
|
||||||
if (attributes == null || attributes.getResponse() == null) {
|
Method targetMethod = this.getMethod(joinPoint);
|
||||||
|
Class<?> targetClass = joinPoint.getTarget().getClass();
|
||||||
|
if (!isRequestRecord(targetMethod, targetClass)) {
|
||||||
return joinPoint.proceed();
|
return joinPoint.proceed();
|
||||||
}
|
}
|
||||||
HttpServletRequest request = attributes.getRequest();
|
|
||||||
HttpServletResponse response = attributes.getResponse();
|
|
||||||
String errorMsg = null;
|
String errorMsg = null;
|
||||||
// 开始记录
|
// 开始记录
|
||||||
LogRecord.Started startedLogRecord = logHandler.start(startTime, request);
|
LogRecord.Started startedLogRecord = logHandler.start(startTime, request);
|
||||||
@@ -95,8 +97,7 @@ public class LogAspect {
|
|||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
Instant endTime = Instant.now();
|
Instant endTime = Instant.now();
|
||||||
Method targetMethod = this.getMethod(joinPoint);
|
HttpServletResponse response = SpringWebUtils.getResponse();
|
||||||
Class<?> targetClass = joinPoint.getTarget().getClass();
|
|
||||||
LogRecord logRecord = logHandler.finish(startedLogRecord, endTime, response, logProperties
|
LogRecord logRecord = logHandler.finish(startedLogRecord, endTime, response, logProperties
|
||||||
.getIncludes(), targetMethod, targetClass);
|
.getIncludes(), targetMethod, targetClass);
|
||||||
// 记录异常信息
|
// 记录异常信息
|
||||||
@@ -111,6 +112,32 @@ public class LogAspect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否要记录日志
|
||||||
|
*
|
||||||
|
* @param targetMethod 目标方法
|
||||||
|
* @param targetClass 目标类
|
||||||
|
* @return true:需要记录;false:不需要记录
|
||||||
|
*/
|
||||||
|
private boolean isRequestRecord(Method targetMethod, Class<?> targetClass) {
|
||||||
|
// 非 Web 环境不记录
|
||||||
|
ServletRequestAttributes attributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
|
||||||
|
if (attributes == null || attributes.getResponse() == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 如果接口匹配排除列表,不记录日志
|
||||||
|
if (logProperties.isMatch(attributes.getRequest().getRequestURI())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 如果接口方法或类上有 @Log 注解,且要求忽略该接口,则不记录日志
|
||||||
|
Log methodLog = AnnotationUtil.getAnnotation(targetMethod, Log.class);
|
||||||
|
if (null != methodLog && methodLog.ignore()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log classLog = AnnotationUtil.getAnnotation(targetClass, Log.class);
|
||||||
|
return null == classLog || !classLog.ignore();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取方法
|
* 获取方法
|
||||||
*
|
*
|
||||||
|
@@ -30,7 +30,9 @@ import top.continew.starter.log.aspect.LogAspect;
|
|||||||
import top.continew.starter.log.dao.LogDao;
|
import top.continew.starter.log.dao.LogDao;
|
||||||
import top.continew.starter.log.dao.impl.DefaultLogDaoImpl;
|
import top.continew.starter.log.dao.impl.DefaultLogDaoImpl;
|
||||||
import top.continew.starter.log.handler.AopLogHandler;
|
import top.continew.starter.log.handler.AopLogHandler;
|
||||||
|
import top.continew.starter.log.handler.LogFilter;
|
||||||
import top.continew.starter.log.handler.LogHandler;
|
import top.continew.starter.log.handler.LogHandler;
|
||||||
|
import top.continew.starter.log.model.LogProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志自动配置
|
* 日志自动配置
|
||||||
@@ -52,6 +54,15 @@ public class LogAutoConfiguration {
|
|||||||
this.logProperties = logProperties;
|
this.logProperties = logProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志过滤器
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
@ConditionalOnMissingBean
|
||||||
|
public LogFilter logFilter() {
|
||||||
|
return new LogFilter(logProperties);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志切面
|
* 日志切面
|
||||||
*
|
*
|
||||||
|
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
|
||||||
* <p>
|
|
||||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* <p>
|
|
||||||
* http://www.gnu.org/licenses/lgpl.html
|
|
||||||
* <p>
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package top.continew.starter.log.autoconfigure;
|
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
|
||||||
import top.continew.starter.core.constant.PropertiesConstants;
|
|
||||||
import top.continew.starter.log.enums.Include;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 日志配置属性
|
|
||||||
*
|
|
||||||
* @author Charles7c
|
|
||||||
* @author echo
|
|
||||||
* @since 1.1.0
|
|
||||||
*/
|
|
||||||
@ConfigurationProperties(PropertiesConstants.LOG)
|
|
||||||
public class LogProperties {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否启用日志
|
|
||||||
*/
|
|
||||||
private boolean enabled = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否打印日志,开启后可打印访问日志(类似于 Nginx access log)
|
|
||||||
* <p>
|
|
||||||
* 不记录日志也支持开启打印访问日志
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
private Boolean isPrint = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 包含信息
|
|
||||||
*/
|
|
||||||
private Set<Include> includes = Include.defaultIncludes();
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
this.enabled = enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Boolean getIsPrint() {
|
|
||||||
return isPrint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIsPrint(Boolean print) {
|
|
||||||
isPrint = print;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Include> getIncludes() {
|
|
||||||
return includes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setIncludes(Set<Include> includes) {
|
|
||||||
this.includes = includes;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -28,7 +28,7 @@ import org.springframework.web.filter.OncePerRequestFilter;
|
|||||||
import org.springframework.web.util.ContentCachingRequestWrapper;
|
import org.springframework.web.util.ContentCachingRequestWrapper;
|
||||||
import org.springframework.web.util.ContentCachingResponseWrapper;
|
import org.springframework.web.util.ContentCachingResponseWrapper;
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
import top.continew.starter.log.autoconfigure.LogProperties;
|
import top.continew.starter.log.model.LogProperties;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package top.continew.starter.log.autoconfigure;
|
package top.continew.starter.log.model;
|
||||||
|
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import top.continew.starter.core.constant.PropertiesConstants;
|
import top.continew.starter.core.constant.PropertiesConstants;
|
@@ -33,6 +33,7 @@ import top.continew.starter.log.handler.InterceptorLogHandler;
|
|||||||
import top.continew.starter.log.handler.LogFilter;
|
import top.continew.starter.log.handler.LogFilter;
|
||||||
import top.continew.starter.log.handler.LogHandler;
|
import top.continew.starter.log.handler.LogHandler;
|
||||||
import top.continew.starter.log.interceptor.LogInterceptor;
|
import top.continew.starter.log.interceptor.LogInterceptor;
|
||||||
|
import top.continew.starter.log.model.LogProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 日志自动配置
|
* 日志自动配置
|
||||||
|
@@ -27,7 +27,7 @@ import org.springframework.lang.NonNull;
|
|||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
import top.continew.starter.log.annotation.Log;
|
import top.continew.starter.log.annotation.Log;
|
||||||
import top.continew.starter.log.autoconfigure.LogProperties;
|
import top.continew.starter.log.model.LogProperties;
|
||||||
import top.continew.starter.log.dao.LogDao;
|
import top.continew.starter.log.dao.LogDao;
|
||||||
import top.continew.starter.log.handler.LogHandler;
|
import top.continew.starter.log.handler.LogHandler;
|
||||||
import top.continew.starter.log.model.LogRecord;
|
import top.continew.starter.log.model.LogRecord;
|
||||||
|
Reference in New Issue
Block a user