package com.vincent.rsf.openApi.aspect; import com.alibaba.fastjson.JSON; import com.vincent.rsf.common.utils.Utils; import com.vincent.rsf.framework.common.Cools; import com.vincent.rsf.openApi.annotation.OperationLog; import com.vincent.rsf.openApi.entity.app.ApiForeignLog; import com.vincent.rsf.openApi.entity.dto.CommonResponse; import com.vincent.rsf.openApi.service.ApiForeignLogService; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; 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 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.rmi.NoSuchObjectException; import java.util.*; /** * Created by Administrator on 2019-07-09. */ @Component @Aspect @Slf4j @Order(2) public class LogAspect { // 参数、返回结果、错误信息等最大保存长度 private static final int MAX_LENGTH = 1000; // 用于记录请求耗时 private final ThreadLocal startTime = new ThreadLocal<>(); @Resource private ApiForeignLogService apiForeignLogService; public LogAspect() { } /** * 切入点 * 匹配controller包及其所有子包下的所有类的所有方法 */ @Pointcut("execution(* com.vincent.rsf.openApi.controller..*.*(..))") public void controllerPc() { } /** * 环绕通知 * @param pjp ProceedingJoinPoint * @return 方法结果 */ @Around("controllerPc()") public Object around(ProceedingJoinPoint pjp) { String methodName = pjp.getSignature().getName(); try { ServletRequestAttributes attributes = Optional.ofNullable((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) .orElseThrow(() -> new NoSuchObjectException("前置通知中获取的 ServletRequestAttributes 对象为空")); HttpServletRequest request = attributes.getRequest(); // if("getToken".equals(methodName) || "getToken".equals(methodName)) // return pjp.proceed(); // 前置通知 log.info("------【前置通知】------"); // 记录请求内容 log.info("浏览器输入的网址:{}", request.getRequestURL().toString()); log.info("HTTP_METHOD:{}", request.getMethod()); log.info("IP:{}", request.getRemoteAddr()); log.info("执行的业务方法名:{}", pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName()); log.info("业务方法获得的参数:{}", Arrays.toString(pjp.getArgs())); Object result = pjp.proceed(); // 后置通知 log.info("------【后置通知】------"); log.info("{}方法的返回值:{}", pjp.getSignature().getName(), result); saveLog1(pjp, result, null); return result; } catch (Throwable e) { // 异常通知 log.error("------【异常通知】------"); log.error("{}方法异常,参数:{},异常:", pjp.getSignature().getName(), Arrays.toString(pjp.getArgs()), e); saveLog1(pjp, null, (Exception) e); return CommonResponse.error("服务器处理数据异常"); } finally { // 最终通知 if(!methodName.isEmpty() && !"getRegistered".equals(methodName)){ log.info("------【最终通知】------"); log.info("{}方法执行结束", pjp.getSignature().getName()); } } } private void saveLog1(JoinPoint joinPoint, Object result, Exception e) { ApiForeignLog record = new ApiForeignLog(); 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()); // } // 记录请求参数 record.setRequest(Utils.sub(Arrays.toString(joinPoint.getArgs()), MAX_LENGTH)); record.setResponse(Utils.sub(JSON.toJSONString(result), MAX_LENGTH)); apiForeignLogService.saveAsync(record); } /** * 保存操作记录 */ 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; } ApiForeignLog record = new ApiForeignLog(); 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)); } apiForeignLogService.saveAsync(record); } /** * 获取操作功能 * * @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; } /** * 获取请求参数 * * @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; } }