当前位置 博文首页 > 无限迭代中......:Spring Boot——基于AOP的HTTP操作日志解决方

    无限迭代中......:Spring Boot——基于AOP的HTTP操作日志解决方

    作者:[db:作者] 时间:2021-07-19 19:23

    解决方案

    package com.hailiu.web.aop;
    
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.hailiu.model.Log;
    import com.hailiu.security.user.AuthenticationUser;
    import com.hailiu.service.ILogService;
    import com.hailiu.web.bean.ResponseBean;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.Signature;
    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 javax.servlet.http.HttpServletRequest;
    
    /**
     * AOP记录用户操作日志
     *
     * @author ShenTuZhiGang
     * @version 1.0.0
     * @date 2021-03-21 18:34
     */
    @Aspect
    @Component
    public class WebLogAspect {
    
        private static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(WebLogAspect.class);
    
        private final ObjectMapper objectMapper;
    
        private final ILogService iLogService;
    
        public WebLogAspect(ObjectMapper objectMapper, ILogService iLogService) {
            this.objectMapper = objectMapper;
            this.iLogService = iLogService;
        }
    
        /**
         * Controller层切点
         */
        @Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
        public void controllerAspect(){
    
        }
    
        @Before("controllerAspect()")
        public void doBefore(JoinPoint joinPoint) {
            logger.info("before");
        }
    
    
        @Around("controllerAspect()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            Signature signature = pjp.getSignature();
            Log log = new Log();
            log.setHttpMethod(request.getMethod());
            log.setHttpUri(request.getRequestURI());
            log.setHttpUserAgent(request.getHeader("User-Agent"));
            log.setHttpRemoteHost(request.getRemoteHost());
            log.setClassName(signature.getDeclaringTypeName());
            log.setMethodName(signature.getName());
            // 处理请求参数
            StringBuilder params = new StringBuilder();
            String[] paramNames = ((MethodSignature) signature).getParameterNames();
            Object[] paramValues = pjp.getArgs();
            int paramLength = null == paramNames ? 0 : paramNames.length;
            if (paramLength == 0) {
                log.setHttpParams("{}");
            } else {
                params.append("[");
                for (int i = 0; i < paramLength ; i++) {
                    if(i > 0){
                        params.append(",");
                    }
                    params.append(paramNames[i]).append("=")
                            .append(objectMapper.writeValueAsString(paramValues[i]));
                }
                params.append("]");
            }
            log.setHttpParams(params.toString());
            log.setOperator(-1);
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (authentication != null && authentication.isAuthenticated()) {
                AuthenticationUser user = (AuthenticationUser) authentication.getPrincipal();
                if(user != null){
                    log.setOperator(user.getId());
                }
            }
            log.setOperationName("普通操作");
            Long start = System.currentTimeMillis();
            try{
                logger.info("before around");
                Object o = pjp.proceed();
                logger.info("after around");
                if(o instanceof ResponseBean){
                    ResponseBean<?> response = (ResponseBean<?>) o;
                    log.setStatus(response.getStatus());
                    log.setMsg(response.getMsg());
                    log.setIsFail(response.getStatus() != 200);
                }else{
                    log.setIsFail(false);
                }
                log.setIsError(false);
                return o;
            }catch (Exception e){
                log.setStatus(500);
                log.setMsg("内部错误");
                log.setIsFail(true);
                log.setIsError(true);
                //return ResponseBean.error("内部错误");
                throw e;
            }finally {
                Long end = System.currentTimeMillis();
                log.setExecuteTime((int) (end - start));
                iLogService.save(log);
            }
        }
    
        @After("controllerAspect()")
        public void doAfter(JoinPoint joinPoint){
            logger.info("after");
        }
    
        @AfterThrowing(pointcut = "controllerAspect()",throwing = "e")
        public void doAfterThrowing(JoinPoint joinPoint,Throwable e){
            logger.info("after throwing");
        }
    
        @AfterReturning(pointcut = "controllerAspect()",returning = "response")
        public void doAfterReturning(JoinPoint joinPoint, ResponseBean<?> response){
            logger.info("after returning");
        }
    }

    参考文章

    springboot + AOP 日志

    springboot项目使用切面记录用户操作日志

    Spring Boot启用http请求日志记录(访问日志)

    cs