212 lines
7.6 KiB
Java
212 lines
7.6 KiB
Java
package com.gxwebsoft.common.core.aspect;
|
|
|
|
import cn.hutool.core.util.ArrayUtil;
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
import cn.hutool.core.util.StrUtil;
|
|
import cn.hutool.extra.servlet.ServletUtil;
|
|
import cn.hutool.http.useragent.UserAgent;
|
|
import cn.hutool.http.useragent.UserAgentUtil;
|
|
import com.gxwebsoft.common.core.annotation.OperationLog;
|
|
import com.gxwebsoft.common.core.annotation.OperationModule;
|
|
import com.gxwebsoft.common.core.utils.JSONUtil;
|
|
import com.gxwebsoft.common.system.entity.OperationRecord;
|
|
import com.gxwebsoft.common.system.entity.User;
|
|
import com.gxwebsoft.common.system.service.OperationRecordService;
|
|
import io.swagger.annotations.Api;
|
|
import io.swagger.annotations.ApiOperation;
|
|
import org.aspectj.lang.JoinPoint;
|
|
import org.aspectj.lang.annotation.*;
|
|
import org.aspectj.lang.reflect.MethodSignature;
|
|
import org.springframework.security.core.Authentication;
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
import org.springframework.stereotype.Component;
|
|
import org.springframework.web.context.request.RequestContextHolder;
|
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
import javax.annotation.Resource;
|
|
import javax.servlet.http.HttpServletRequest;
|
|
import javax.servlet.http.HttpServletResponse;
|
|
import java.lang.reflect.Method;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* 操作日志记录
|
|
*
|
|
* @author WebSoft
|
|
* @since 2020-03-21 16:58:16:05
|
|
*/
|
|
@Aspect
|
|
@Component
|
|
public class OperationLogAspect {
|
|
@Resource
|
|
private OperationRecordService operationRecordService;
|
|
|
|
// 参数、返回结果、错误信息等最大保存长度
|
|
private static final int MAX_LENGTH = 1000;
|
|
// 用于记录请求耗时
|
|
private final ThreadLocal<Long> startTime = new ThreadLocal<>();
|
|
|
|
@Pointcut("@annotation(com.gxwebsoft.common.core.annotation.OperationLog)")
|
|
public void operationLog() {
|
|
}
|
|
|
|
@Before("operationLog()")
|
|
public void doBefore(JoinPoint joinPoint) throws Throwable {
|
|
startTime.set(System.currentTimeMillis());
|
|
}
|
|
|
|
@AfterReturning(pointcut = "operationLog()", returning = "result")
|
|
public void doAfterReturning(JoinPoint joinPoint, Object result) {
|
|
saveLog(joinPoint, result, null);
|
|
}
|
|
|
|
@AfterThrowing(value = "operationLog()", throwing = "e")
|
|
public void doAfterThrowing(JoinPoint joinPoint, Exception e) {
|
|
saveLog(joinPoint, null, e);
|
|
}
|
|
|
|
/**
|
|
* 保存操作记录
|
|
*/
|
|
private void saveLog(JoinPoint joinPoint, Object result, Exception e) {
|
|
OperationRecord record = new OperationRecord();
|
|
// 记录操作耗时
|
|
if (startTime.get() != null) {
|
|
record.setSpendTime(System.currentTimeMillis() - startTime.get());
|
|
}
|
|
// 记录当前登录用户id、租户id
|
|
User user = getLoginUser();
|
|
if (user != null) {
|
|
record.setUserId(user.getUserId());
|
|
record.setTenantId(user.getTenantId());
|
|
}
|
|
// 记录请求地址、请求方式、ip
|
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
|
HttpServletRequest request = (attributes == null ? null : attributes.getRequest());
|
|
if (request != null) {
|
|
record.setUrl(request.getRequestURI());
|
|
record.setRequestMethod(request.getMethod());
|
|
UserAgent ua = UserAgentUtil.parse(ServletUtil.getHeaderIgnoreCase(request, "User-Agent"));
|
|
record.setOs(ua.getPlatform().toString());
|
|
record.setDevice(ua.getOs().toString());
|
|
record.setBrowser(ua.getBrowser().toString());
|
|
record.setIp(ServletUtil.getClientIP(request));
|
|
}
|
|
// 记录异常信息
|
|
if (e != null) {
|
|
record.setStatus(1);
|
|
record.setError(StrUtil.sub(e.toString(), 0, MAX_LENGTH));
|
|
}
|
|
// 记录模块名、操作功能、请求方法、请求参数、返回结果
|
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
|
record.setMethod(joinPoint.getTarget().getClass().getName() + "." + signature.getName());
|
|
Method method = signature.getMethod();
|
|
if (method != null) {
|
|
OperationLog ol = method.getAnnotation(OperationLog.class);
|
|
if (ol != null) {
|
|
// 记录操作功能
|
|
record.setDescription(getDescription(method, ol));
|
|
// 记录操作模块
|
|
record.setModule(getModule(joinPoint, ol));
|
|
// 记录备注
|
|
if (StrUtil.isNotEmpty(ol.comments())) {
|
|
record.setComments(ol.comments());
|
|
}
|
|
// 记录请求参数
|
|
if (ol.param() && request != null) {
|
|
record.setParams(StrUtil.sub(getParams(joinPoint, request), 0, MAX_LENGTH));
|
|
}
|
|
// 记录请求结果
|
|
if (ol.result() && result != null) {
|
|
record.setResult(StrUtil.sub(JSONUtil.toJSONString(result), 0, MAX_LENGTH));
|
|
}
|
|
}
|
|
}
|
|
operationRecordService.saveAsync(record);
|
|
}
|
|
|
|
/**
|
|
* 获取当前登录用户
|
|
*/
|
|
private User getLoginUser() {
|
|
Authentication subject = SecurityContextHolder.getContext().getAuthentication();
|
|
if (subject != null) {
|
|
Object object = subject.getPrincipal();
|
|
if (object instanceof User) {
|
|
return (User) object;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 获取请求参数
|
|
*
|
|
* @param joinPoint JoinPoint
|
|
* @param request HttpServletRequest
|
|
* @return String
|
|
*/
|
|
private String getParams(JoinPoint joinPoint, HttpServletRequest request) {
|
|
String params;
|
|
Map<String, String> paramsMap = ServletUtil.getParamMap(request);
|
|
if (paramsMap.keySet().size() > 0) {
|
|
params = JSONUtil.toJSONString(paramsMap);
|
|
} else {
|
|
StringBuilder sb = new StringBuilder();
|
|
for (Object arg : joinPoint.getArgs()) {
|
|
if (ObjectUtil.isNull(arg)
|
|
|| arg instanceof MultipartFile
|
|
|| arg instanceof HttpServletRequest
|
|
|| arg instanceof HttpServletResponse) {
|
|
continue;
|
|
}
|
|
sb.append(JSONUtil.toJSONString(arg)).append(" ");
|
|
}
|
|
params = sb.toString();
|
|
}
|
|
return params;
|
|
}
|
|
|
|
/**
|
|
* 获取操作模块
|
|
*
|
|
* @param joinPoint JoinPoint
|
|
* @param ol OperationLog
|
|
* @return String
|
|
*/
|
|
private String getModule(JoinPoint joinPoint, OperationLog ol) {
|
|
if (StrUtil.isNotEmpty(ol.module())) {
|
|
return ol.module();
|
|
}
|
|
OperationModule om = joinPoint.getTarget().getClass().getAnnotation(OperationModule.class);
|
|
if (om != null && StrUtil.isNotEmpty(om.value())) {
|
|
return om.value();
|
|
}
|
|
Api api = joinPoint.getTarget().getClass().getAnnotation(Api.class);
|
|
if (api != null && api.tags() != null) {
|
|
return ArrayUtil.join(api.tags(), ",");
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* 获取操作功能
|
|
*
|
|
* @param method Method
|
|
* @param ol OperationLog
|
|
* @return String
|
|
*/
|
|
private String getDescription(Method method, OperationLog ol) {
|
|
if (StrUtil.isNotEmpty(ol.value())) {
|
|
return ol.value();
|
|
}
|
|
ApiOperation ao = method.getAnnotation(ApiOperation.class);
|
|
if (ao != null && StrUtil.isNotEmpty(ao.value())) {
|
|
return ao.value();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
}
|