| package com.ruoyi.framework.aspectj; | 
|   | 
| import java.util.Collection; | 
| import java.util.Map; | 
| import javax.servlet.http.HttpServletRequest; | 
| import javax.servlet.http.HttpServletResponse; | 
|   | 
| 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.slf4j.Logger; | 
| import org.slf4j.LoggerFactory; | 
| import org.springframework.stereotype.Component; | 
| import org.springframework.validation.BindingResult; | 
| import org.springframework.web.multipart.MultipartFile; | 
| import com.alibaba.fastjson2.JSON; | 
| import com.ruoyi.common.annotation.Log; | 
| import com.ruoyi.common.core.domain.model.LoginUser; | 
| import com.ruoyi.common.enums.BusinessStatus; | 
| import com.ruoyi.common.enums.HttpMethod; | 
| import com.ruoyi.common.filter.PropertyPreExcludeFilter; | 
| import com.ruoyi.common.utils.SecurityUtils; | 
| import com.ruoyi.common.utils.ServletUtils; | 
| import com.ruoyi.common.utils.StringUtils; | 
| import com.ruoyi.common.utils.ip.IpUtils; | 
| import com.ruoyi.framework.manager.AsyncManager; | 
| import com.ruoyi.framework.manager.factory.AsyncFactory; | 
| import com.ruoyi.system.domain.SysOperLog; | 
|   | 
| /** | 
|  * 操作日志记录处理 | 
|  * | 
|  * @author ruoyi | 
|  */ | 
| @Aspect | 
| @Component | 
| public class LogAspect { | 
|     private static final Logger log = LoggerFactory.getLogger(LogAspect.class); | 
|   | 
|     /** | 
|      * 排除敏感属性字段 | 
|      */ | 
|     public static final String[] EXCLUDE_PROPERTIES = {"password", "oldPassword", "newPassword", "confirmPassword"}; | 
|   | 
|     /** | 
|      * 处理完请求后执行 | 
|      * | 
|      * @param joinPoint 切点 | 
|      */ | 
|     @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") | 
|     public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) { | 
|         handleLog(joinPoint, controllerLog, null, jsonResult); | 
|     } | 
|   | 
|     /** | 
|      * 拦截异常操作 | 
|      * | 
|      * @param joinPoint 切点 | 
|      * @param e         异常 | 
|      */ | 
|     @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") | 
|     public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) { | 
|         handleLog(joinPoint, controllerLog, e, null); | 
|     } | 
|   | 
|     protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) { | 
|         try { | 
|             // 获取当前的用户 | 
|             LoginUser loginUser = SecurityUtils.getLoginUser(); | 
|   | 
|             // *========数据库日志=========*// | 
|             SysOperLog operLog = new SysOperLog(); | 
|             operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); | 
|             // 请求的地址 | 
|             String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); | 
|             operLog.setOperIp(ip); | 
|             operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); | 
|             if (loginUser != null) { | 
|                 operLog.setOperName(loginUser.getUsername()); | 
|             } | 
|   | 
|             if (e != null) { | 
|                 operLog.setStatus(BusinessStatus.FAIL.ordinal()); | 
|                 operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000)); | 
|             } | 
|             // 设置方法名称 | 
|             String className = joinPoint.getTarget().getClass().getName(); | 
|             String methodName = joinPoint.getSignature().getName(); | 
|             operLog.setMethod(className + "." + methodName + "()"); | 
|             // 设置请求方式 | 
|             operLog.setRequestMethod(ServletUtils.getRequest().getMethod()); | 
|             // 处理设置注解上的参数 | 
|             getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); | 
|             //判断状态码 | 
|             Map resultMap = (Map) jsonResult; | 
|             if (StringUtils.isNotNull(resultMap)) { | 
|                 if (resultMap.get("code").equals(500)) { | 
|                     operLog.setStatus(BusinessStatus.FAIL.ordinal()); | 
|                 } | 
|             } | 
|             // 保存数据库 | 
|             AsyncManager.me().execute(AsyncFactory.recordOper(operLog)); | 
|         } catch (Exception exp) { | 
|             // 记录本地异常日志 | 
|             log.error("异常信息:{}", exp.getMessage()); | 
|             exp.printStackTrace(); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 获取注解中对方法的描述信息 用于Controller层注解 | 
|      * | 
|      * @param log     日志 | 
|      * @param operLog 操作日志 | 
|      * @throws Exception | 
|      */ | 
|     public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception { | 
|         // 设置action动作 | 
|         operLog.setBusinessType(log.businessType().ordinal()); | 
|         // 设置标题 | 
|         operLog.setTitle(log.title()); | 
|         // 设置操作人类别 | 
|         operLog.setOperatorType(log.operatorType().ordinal()); | 
|         // 是否需要保存request,参数和值 | 
|         if (log.isSaveRequestData()) { | 
|             // 获取参数的信息,传入到数据库中。 | 
|             setRequestValue(joinPoint, operLog); | 
|         } | 
|         // 是否需要保存response,参数和值 | 
|         if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult)) { | 
|             operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000)); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 获取请求的参数,放到log中 | 
|      * | 
|      * @param operLog 操作日志 | 
|      * @throws Exception 异常 | 
|      */ | 
|     private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception { | 
|         String requestMethod = operLog.getRequestMethod(); | 
|         if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { | 
|             String params = argsArrayToString(joinPoint.getArgs()); | 
|             operLog.setOperParam(StringUtils.substring(params, 0, 2000)); | 
|         } else { | 
|             Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); | 
|             operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter()), 0, 2000)); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 参数拼装 | 
|      */ | 
|     private String argsArrayToString(Object[] paramsArray) { | 
|         String params = ""; | 
|         if (paramsArray != null && paramsArray.length > 0) { | 
|             for (Object o : paramsArray) { | 
|                 if (StringUtils.isNotNull(o) && !isFilterObject(o)) { | 
|                     try { | 
|                         String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter()); | 
|                         params += jsonObj.toString() + " "; | 
|                     } catch (Exception e) { | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|         return params.trim(); | 
|     } | 
|   | 
|     /** | 
|      * 忽略敏感属性 | 
|      */ | 
|     public PropertyPreExcludeFilter excludePropertyPreFilter() { | 
|         return new PropertyPreExcludeFilter().addExcludes(EXCLUDE_PROPERTIES); | 
|     } | 
|   | 
|     /** | 
|      * 判断是否需要过滤的对象。 | 
|      * | 
|      * @param o 对象信息。 | 
|      * @return 如果是需要过滤的对象,则返回true;否则返回false。 | 
|      */ | 
|     @SuppressWarnings("rawtypes") | 
|     public boolean isFilterObject(final Object o) { | 
|         Class<?> clazz = o.getClass(); | 
|         if (clazz.isArray()) { | 
|             return clazz.getComponentType().isAssignableFrom(MultipartFile.class); | 
|         } else if (Collection.class.isAssignableFrom(clazz)) { | 
|             Collection collection = (Collection) o; | 
|             for (Object value : collection) { | 
|                 return value instanceof MultipartFile; | 
|             } | 
|         } else if (Map.class.isAssignableFrom(clazz)) { | 
|             Map map = (Map) o; | 
|             for (Object value : map.entrySet()) { | 
|                 Map.Entry entry = (Map.Entry) value; | 
|                 return entry.getValue() instanceof MultipartFile; | 
|             } | 
|         } | 
|         return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse | 
|                 || o instanceof BindingResult; | 
|     } | 
| } |