ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

springboot中使用aop记录操作和异常日志

2021-03-28 09:01:08  阅读:207  来源: 互联网

标签:COMMENT oper String DEFAULT request aop 日志 NULL springboot


一、创建日志记录表、异常日志表,表结构如下:

操作表:
在这里插入图片描述
异常表:
在这里插入图片描述
DDL:

CREATE TABLE `operlog` (
  `oper_id` varchar(64) NOT NULL COMMENT '主键',
  `oper_model` varchar(64) DEFAULT NULL COMMENT '功能模块',
  `oper_type` varchar(64) DEFAULT NULL COMMENT '操作类型',
  `oper_desc` varchar(500) DEFAULT NULL COMMENT '操作描述',
  `oper_requ_param` text COMMENT '请求参数',
  `oper_resp_param` text COMMENT '返回参数',
  `oper_user_id` varchar(64) DEFAULT NULL COMMENT '操作员id',
  `oper_user_name` varchar(64) DEFAULT NULL COMMENT '操作员名称',
  `oper_method` varchar(255) DEFAULT NULL COMMENT '操作方法',
  `oper_uri` varchar(255) DEFAULT NULL COMMENT '请求URI',
  `oper_ip` varchar(64) DEFAULT NULL COMMENT '请求id',
  `oper_create_time` datetime DEFAULT NULL COMMENT '操作时间',
  `oper_ver` varchar(64) DEFAULT NULL COMMENT '操作版本号',
  PRIMARY KEY (`oper_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `errorlog` (
  `error_id` varchar(64) NOT NULL COMMENT '主键ID',
  `oper_user_id` varchar(64) DEFAULT NULL COMMENT '操作员ID',
  `oper_user_name` varchar(64) DEFAULT NULL COMMENT '操作员名称',
  `oper_method` varchar(255) DEFAULT NULL COMMENT '操作方法',
  `oper_uri` varchar(255) DEFAULT NULL COMMENT '请求URI',
  `oper_ip` varchar(64) DEFAULT NULL COMMENT '请求IP',
  `oper_ver` varchar(64) DEFAULT NULL COMMENT '操作版本',
  `oper_create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `error_requ_param` text COMMENT '请求参数',
  `error_name` varchar(255) DEFAULT NULL COMMENT '异常名称',
  `error_message` text COMMENT '异常信息',
  PRIMARY KEY (`error_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

二、添加Maven依赖

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

创建操作日志注解类OperLog.java和操作类型类

//注解放置的目标位置,METHOD是可注解在方法级别上
@Target(ElementType.METHOD)
//注解在哪个阶段执行
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperLog {
    // 操作模块
    String operModul() default "";
    // 操作类型
    LogActionType operType() default LogActionType.SELECT;
    // 操作说明
    String operDesc() default "";
}
public enum LogActionType {
    /**
     * 增删改查
     */
    ADD("新增"),
    SELECT("查询"),
    UPDATE("更新"),
    DELETE("删除");
    private String value;

    LogActionType(String value) {
        this.value = value;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

创建切面类记录操作日志

/**
 * 切片的实现
 * 监控controller的请求信息和响应信息
 *
 * @author sxyuser
 */
@Aspect
@Slf4j
@Component
public class WebLogAspect {
    /**
     * 操作版本号
     * <p>
     * 项目启动时从命令行传入,例如:java -jar xxx.war --version=201902
     * </p>
     */
//    @Value("${version}")
    private final String operVer = "1";

    @Resource
    private ErrorlogService errorlogService;

    @Resource
    private OperlogService operlogService;

    /**
     * 设置操作日志切入点 记录操作日志 在注解的位置切入代码
     */
    @Pointcut("@annotation(com.demo.shiyan2.utils.annotation.OperLog)")
    public void operLogPoinCut() {
    }

    /**
     * 设置操作异常切入点记录异常日志 扫描所有controller包下操作
     */
    @Pointcut("execution(* com.demo.shiyan2.controller..*.*(..))")
    public void operExceptionLogPoinCut() {
    }

    /**
     * 配置环绕通知,使用在方法logPointcut()上注册的切入点
     *
     * @param joinPoint join point for advice
     */
    @Before(value = "operLogPoinCut()")
    public void doBefore(JoinPoint joinPoint) {
        HttpServletRequest request = RequestHolder.getHttpServletRequest();
        if (request != null) {
                // 记录下请求内容
                log.info("URL : {}", request.getRequestURL().toString());
                log.info("HTTP_METHOD :{} ", request.getMethod());
                log.info("IP : {}", request.getRemoteAddr());
                log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
                log.info("ARGS : " + JsonUtils.obiectToJson(joinPoint.getArgs()));
                Enumeration<String> enu = request.getParameterNames();
                while (enu.hasMoreElements()) {
                    String name = enu.nextElement();
                    log.info("name:{},value:{}", name, request.getParameter(name));
                }
        } else {
            log.error("ServletRequestAttributes为空!");
        }
    }

    /**
     * 正常返回通知,拦截用户操作日志,连接点正常执行完成后执行, 如果连接点抛出异常,则不会执行
     *
     * @param joinPoint 切入点
     * @param keys      返回结果
     */
    @AfterReturning(value = "operExceptionLogPoinCut()", returning = "keys")
    public void saveOperLog(JoinPoint joinPoint, Object keys) {
        HttpServletRequest request = RequestHolder.getHttpServletRequest();
        if (request != null) {
            Operlog operlog = new Operlog();
                // 主键ID
                operlog.setOperId(UUID.randomUUID().toString());

                // 从切面织入点处通过反射机制获取织入点处的方法
                MethodSignature signature = (MethodSignature) joinPoint.getSignature();
                // 获取切入点所在的方法
                Method method = signature.getMethod();
                // 获取操作
                OperLog opLog = method.getAnnotation(OperLog.class);
                if (opLog != null) {
                    String operModul = opLog.operModul();
                    String operType = JsonUtils.obiectToJson(opLog.operType());
                    String operDesc = opLog.operDesc();
                    // 操作模块
                    operlog.setOperModel(operModul);
                    // 操作类型
                    operlog.setOperType(operType);
                    // 操作描述
                    operlog.setOperDesc(operDesc);
                }
                // 获取请求的类名
                String className = joinPoint.getTarget().getClass().getName();
                // 获取请求的方法名
                String methodName = method.getName();
                methodName = className + "." + methodName;
                // 请求方法
                operlog.setOperMethod(methodName);
                // 将参数所在的数组转换成json
                String params = JsonUtils.obiectToJson(request.getParameterMap());
                // 请求参数
                operlog.setOperRequParam(params);
                // 返回结果
                operlog.setOperRespParam(JsonUtils.obiectToJson(keys));
//            operlog.setOperUserId(UserShiroUtil.getCurrentUserLoginName()); // 请求用户ID
//            operlog.setOperUserName(UserShiroUtil.getCurrentUserName()); // 请求用户名称
                // 请求IP
                operlog.setOperIp(request.getRemoteAddr());
                // 请求URI
                operlog.setOperUri(request.getRequestURI());
                // 创建时间
                operlog.setOperCreateTime(Instant.now());
                // 操作版本
                operlog.setOperVer(operVer);
                operlogService.save(operlog);
        } else {
            log.error("ServletRequestAttributes为空!");
        }
    }

    /**
     * 异常返回通知,用于拦截异常日志信息 连接点抛出异常后执行
     *
     * @param joinPoint 切入点
     * @param e         异常信息
     */
    @AfterThrowing(pointcut = "operLogPoinCut()", throwing = "e")
    public void saveExceptionLog(JoinPoint joinPoint, Throwable e) {
        try {
            HttpServletRequest request = RequestHolder.getHttpServletRequest();
            if (request != null) {
                Errorlog excepLog = new Errorlog();
                // 从切面织入点处通过反射机制获取织入点处的方法
                MethodSignature signature = (MethodSignature) joinPoint.getSignature();
                // 获取切入点所在的方法
                Method method = signature.getMethod();
                excepLog.setErrorId(UUID.randomUUID().toString());
                // 获取请求的类名
                String className = joinPoint.getTarget().getClass().getName();
                // 获取请求的方法名
                String methodName = method.getName();
                methodName = className + "." + methodName;
                // 将参数所在的数组转换成json
                String params = JsonUtils.obiectToJson(request.getParameterMap());
                excepLog.setErrorRequParam(params); // 请求参数
                excepLog.setOperMethod(methodName); // 请求方法名
                excepLog.setErrorName(e.getClass().getName()); // 异常名称
                excepLog.setErrorMessage(stackTraceToString(e.getClass().getName(), e.getMessage(), e.getStackTrace()));
                // 异常信息
//            excepLog.setOperUserId(UserShiroUtil.getCurrentUserLoginName()); // 操作员ID
//            excepLog.setOperUserName(UserShiroUtil.getCurrentUserName()); // 操作员名称
                // 操作URI
                excepLog.setOperUri(request.getRequestURI());
                // 操作员IP
                excepLog.setOperIp(request.getRemoteAddr());
                // 操作版本号
                excepLog.setOperVer(operVer);
                // 发生异常时间
                excepLog.setOperCreateTime(Instant.now());
                errorlogService.save(excepLog);
            } else {
                log.error("ServletRequestAttributes为空!");
            }
        } catch (Exception e2) {
            e2.printStackTrace();
        }


    }

    /**
     * 转换异常信息为字符串
     *
     * @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.toString();
    }
}

RequestHolder类

/**
 * 获取 HttpServletRequest
 */
public class RequestHolder {

    public static HttpServletRequest getHttpServletRequest() {
        HttpServletRequest request=null;
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (attributes != null) {
            request = attributes.getRequest();
        }
        return request;
    }
}

位于JsonUtils类中的obiectToJson方法

 public static String obiectToJson(Object object) {
        try {
            return objectMapper.writeValueAsString(object);
        } catch (Exception e) {
            return null;
        }
    }

在Controller层方法添加@OperLog注解

 @OperLog(operModul = "测试类",operType = LogActionType.ADD,operDesc = "测试方法")
    @GetMapping("/")
    public String test(HttpServletRequest request) {
        userService.test();
        return request.getRequestURI();
    }

操作日志、异常日志查询功能

在这里插入图片描述

标签:COMMENT,oper,String,DEFAULT,request,aop,日志,NULL,springboot
来源: https://blog.csdn.net/weixin_43897590/article/details/115276006

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有