package com.izouma.nineth.aspect; import com.alibaba.fastjson.JSON; import com.izouma.nineth.annotations.OperLog; import com.izouma.nineth.domain.ExceptionLog; import com.izouma.nineth.domain.OperationLog; import com.izouma.nineth.domain.User; import com.izouma.nineth.repo.ExceptionLogRepo; import com.izouma.nineth.repo.OperationLogRepo; import com.izouma.nineth.utils.IPUtils; import com.izouma.nineth.utils.SecurityUtils; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; @Aspect @Component public class OperLogAspect { @Autowired private OperationLogRepo operationLogRepo; @Autowired private ExceptionLogRepo exceptionLogRepo; /** * 设置操作日志切入点 记录操作日志 在注解的位置切入代码 */ @Pointcut("@annotation(com.izouma.nineth.annotations.OperLog)") public void operLogPointCut() { } /** * 设置操作异常切入点记录异常日志 扫描所有controller包下操作 */ @Pointcut("execution(* com.izouma.nineth.web..*.*(..))") public void operExceptionLogPointCut() { } /** * 正常返回通知,拦截用户操作日志,连接点正常执行完成后执行, 如果连接点抛出异常,则不会执行 * * @param joinPoint 切入点 * @param keys 返回结果 */ @AfterReturning(value = "operLogPointCut()", returning = "keys") public void saveOperLog(JoinPoint joinPoint, Object keys) { // 获取RequestAttributes RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); // 从获取RequestAttributes中获取HttpServletRequest的信息 HttpServletRequest request = (HttpServletRequest) requestAttributes .resolveReference(RequestAttributes.REFERENCE_REQUEST); OperationLog operationLog = new OperationLog(); try { // 从切面织入点处通过反射机制获取织入点处的方法 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); // 获取切入点所在的方法 Method method = signature.getMethod(); // 获取操作 OperLog operLog = method.getAnnotation(OperLog.class); if (operLog != null) { operationLog.setName(operLog.value()); // 操作模块 operationLog.setType(operLog.type()); // 操作类型 operationLog.setDesc(operLog.desc()); // 操作描述 } // 获取请求的类名 String className = joinPoint.getTarget().getClass().getName(); // 获取请求的方法名 String methodName = method.getName(); methodName = className + "." + methodName; operationLog.setReqMethod(methodName); // 请求的参数 Map rtnMap = null; String params = null; if (request != null) { rtnMap = convertMap(request.getParameterMap()); params = JSON.toJSONString(rtnMap); } operationLog.setReqParams(params); operationLog.setResp(JSON.toJSONString(keys)); User user = SecurityUtils.getAuthenticatedUser(); if (user != null) { operationLog.setUserId(String.valueOf(user.getId())); operationLog.setUsername(user.getUsername()); } operationLog.setReqIp(IPUtils.getIpAddr(request)); operationLog.setReqUrl(request != null ? request.getRequestURI() : null); operationLog.setTime(LocalDateTime.now()); operationLogRepo.save(operationLog); } catch (Exception e) { e.printStackTrace(); } } /** * 异常返回通知,用于拦截异常日志信息 连接点抛出异常后执行 * * @param joinPoint 切入点 * @param e 异常信息 */ @AfterThrowing(pointcut = "operExceptionLogPointCut()", throwing = "e") public void saveExceptionLog(JoinPoint joinPoint, Throwable e) { // 获取RequestAttributes RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); // 从获取RequestAttributes中获取HttpServletRequest的信息 HttpServletRequest request = (HttpServletRequest) requestAttributes .resolveReference(RequestAttributes.REFERENCE_REQUEST); ExceptionLog exceptionLog = new ExceptionLog(); try { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); String className = joinPoint.getTarget().getClass().getName(); String methodName = method.getName(); methodName = className + "." + methodName; exceptionLog.setReqMethod(methodName); Map rtnMap = convertMap(request.getParameterMap()); String params = JSON.toJSONString(rtnMap); exceptionLog.setReqParams(params); exceptionLog.setName(e.getClass().getName()); exceptionLog.setMessage(stackTraceToString(e.getClass().getName(), e.getMessage(), e .getStackTrace())); User user = SecurityUtils.getAuthenticatedUser(); if (user != null) { exceptionLog.setUserId(String.valueOf(user.getId())); exceptionLog.setUsername(user.getUsername()); } exceptionLog.setReqUrl(request.getRequestURI()); exceptionLog.setReqIp(IPUtils.getIpAddr(request)); exceptionLog.setTime(LocalDateTime.now()); exceptionLogRepo.save(exceptionLog); } catch (Exception e2) { e2.printStackTrace(); } } /** * 转换request 请求参数 * * @param paramMap request获取的参数数组 */ public Map convertMap(Map paramMap) { Map rtnMap = new HashMap<>(); for (String key : paramMap.keySet()) { rtnMap.put(key, paramMap.get(key)[0]); } return rtnMap; } /** * 转换异常信息为字符串 * * @param exceptionName 异常名称 * @param exceptionMessage 异常信息 * @param elements 堆栈信息 */ public String stackTraceToString(String exceptionName, String exceptionMessage, StackTraceElement[] elements) { StringBuilder strBuff = new StringBuilder(); for (StackTraceElement stet : elements) { strBuff.append(stet).append("\n"); } return exceptionName + ":" + exceptionMessage + "\n\t" + strBuff; } }