package com.vincent.rsf.server.common.aspect; import com.alibaba.fastjson.JSON; import com.vincent.rsf.common.utils.Utils; import com.vincent.rsf.framework.common.Cools; import com.vincent.rsf.server.common.annotation.OperationLog; import com.vincent.rsf.server.common.utils.IpTools; import com.vincent.rsf.server.system.entity.OperationRecord; import com.vincent.rsf.server.system.entity.User; import com.vincent.rsf.server.system.service.OperationRecordService; 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.Collections; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * 操作日志记录 * * @author vincent * @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 startTime = new ThreadLocal<>(); @Pointcut("@annotation(com.vincent.rsf.server.common.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) { // 记录模块名、操作功能、请求方法、请求参数、返回结果 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); if (null == method) { return; } OperationLog ol = method.getAnnotation(OperationLog.class); if (null == ol) { return; } String desc = getDescription(method, ol); if (Cools.isEmpty(desc)) { return; } OperationRecord record = new OperationRecord(); Long endTime = startTime.get(); record.setCreateTime(new Date()); // 记录操作耗时 if (endTime != null) { record.setSpendTime((int) (System.currentTimeMillis() - endTime)); } record.setTimestamp(String.valueOf(endTime)); // 记录当前登录用户id、租户id User user = getLoginUser(); if (user != null) { record.setUserId(user.getId()); 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.setClientIp(IpTools.gainRealIp(request)); } // 记录异常信息 if (e != null) { record.setResult(0); record.setErr(Utils.sub(e.toString(), MAX_LENGTH)); } else { record.setResult(1); } // 记录操作功能 record.setNamespace(desc); // 记录备注 if (!Cools.isEmpty(ol.comments())) { record.setMemo(ol.comments()); } // 记录请求参数 if (ol.param() && request != null) { record.setRequest(Utils.sub(getParams(joinPoint, request), MAX_LENGTH)); } // 记录请求结果 if (ol.result() && result != null) { record.setResponse(Utils.sub(JSON.toJSONString(result), 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 paramsMap = new HashMap<>(); Map map = Collections.unmodifiableMap(request.getParameterMap()); for (Map.Entry entry : map.entrySet()) { paramsMap.put(entry.getKey(), Utils.join(entry.getValue(), ",")); } if (paramsMap.keySet().size() > 0) { params = JSON.toJSONString(paramsMap); } else { StringBuilder sb = new StringBuilder(); for (Object arg : joinPoint.getArgs()) { if (null == arg || arg instanceof MultipartFile || arg instanceof HttpServletRequest || arg instanceof HttpServletResponse) { continue; } sb.append(JSON.toJSONString(arg)).append(" "); } params = sb.toString(); } return params; } /** * 获取操作功能 * * @param method Method * @param ol OperationLog * @return String */ private String getDescription(Method method, OperationLog ol) { if (!Cools.isEmpty(ol.value())) { return ol.value(); } return null; } }