SpringBoot使用APO记录操作日志
通过织入自定义注解 @Log,再进行解析记录操作日志。
自定义注解 @Log
java@Target({ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Log { /** * 模块 */ String title() default "default"; /** * 业务类型 */ BusinessType businessType() default BusinessType.OTHER; /** * 是否需要保存request参数和值 */ boolean isSaveRequestData() default true; }
使用
java@GetMapping("/skb_capture/startOrStop") @Log(title = "探针管理", businessType = BusinessType.UPDATE) public R<String> startOrStopAgentSkbCapture(@RequestParam("id") Integer[] id, @RequestParam("operate") String operate) { return R.ok(agentStatusService.startOrStopHcMineSkbCapture(id, operate)); }
LogAspect 类
java@Aspect @Component @Slf4j public class LogAspect { @Autowired private SysOperLogServiceImpl logService; // 配置织入点 @Pointcut("@annotation(org.vlis.apm.server.web.annotation.Log)") public void logPointCut() { } /** * 处理完请求后执行 * * @param joinPoint 切点 */ @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult") public void doAfterReturning(JoinPoint joinPoint, Object jsonResult) { handleLog(joinPoint, null, jsonResult); } /** * 拦截异常操作 * * @param joinPoint 切点 * @param e 异常 */ @AfterThrowing(value = "logPointCut()", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Exception e) { handleLog(joinPoint, e, null); } protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult) { try { // 获得注解 Log controllerLog = getAnnotationLog(joinPoint); if (controllerLog == null) { return; } // *========数据库日志=========*// SysOperLog operLog = new SysOperLog(); operLog.setStatus(0); HttpServletRequest request = getRequest(); if (request == null) { return; } // 请求的地址 String ip = ServletUtil.getClientIP(request); operLog.setOperIp(ip); // 返回参数 operLog.setJsonResult(JSONUtil.toJsonStr(jsonResult)); operLog.setOperUrl(request.getRequestURI()); String username = Convert.toStr(request.getHeader("h-username"), StrUtil.EMPTY); if (StrUtil.isNotBlank(username)) { operLog.setOperName(username); } if (e != null) { operLog.setStatus(1); operLog.setErrorMsg(ExceptionUtil.stacktraceToString(e, 1000)); } String className = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); operLog.setMethod(className + "." + methodName + "()"); operLog.setRequestMethod(request.getMethod()); // 处理设置注解上的参数 getControllerMethodDescription(joinPoint, controllerLog, operLog); //同步入库 logService.save(operLog); } catch (Exception exp) { log.error("日志aop异常", exp); } } public HttpServletRequest getRequest() { try { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); if (requestAttributes == null) { return null; } ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); return servletRequestAttributes.getRequest(); } catch (Exception e) { log.error("获取request异常", e); } return null; } /** * 获取注解中对方法的描述信息 用于Controller层注解 * * @param log 日志 * @param operLog 操作日志 */ public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) { // 设置action动作 operLog.setBusinessType(log.businessType().ordinal()); // 设置标题 operLog.setTitle(log.title()); // 是否需要保存request,参数和值 if (log.isSaveRequestData()) { // 获取参数的信息,传入到数据库中。 setRequestValue(joinPoint, operLog); } } /** * 获取请求的参数,放到log中 * * @param operLog 操作日志 */ private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) { String requestMethod = operLog.getRequestMethod(); if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)|| HttpMethod.DELETE.name().equals(requestMethod)|| HttpMethod.GET.name().equals(requestMethod)) { String params = argsArrayToString(joinPoint.getArgs()); operLog.setOperParam(StrUtil.sub(params, 0, 2000)); } } /** * 是否存在注解,如果存在就获取 */ private Log getAnnotationLog(JoinPoint joinPoint) { Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); if (method != null) { return method.getAnnotation(Log.class); } return null; } /** * 参数拼装 */ private String argsArrayToString(Object[] paramsArray) { StringBuilder params = new StringBuilder(StrUtil.EMPTY); if (ArrayUtil.isNotEmpty(paramsArray)) { for (Object o : paramsArray) { if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) { try { String jsonObj = JSONUtil.toJsonStr(o); params.append(jsonObj).append(" "); } catch (Exception e) { log.error("", e); } } } } return params.toString().trim(); } /** * 判断是否需要过滤的对象。 * * @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; } }