AOP自定义注解实现日志记录

1、定义注解

/**
 * ClassName Crmlog
 * AOP日志记录 自定义注解类
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemCrmlog {
    /**
     * 日志描述
     * 对于什么表格进行了什么操作
     */
    String description() default "";

    /**
     * 操作了的表名
     *
     * @return
     */
    String tableName() default "";
}

2、定义日志实体

/**
 * @ClassName CrmLogMessage
 * @Author Administrator
 * @Describe 数据库日志类
 */
public class CrmLogMessage {
    private Integer logid;//日志id
    private String UserName;//管理员姓名
    private String UserRole;//管理员角色
    private String Content;//日志描述
    private String Remarks;//参数集合
    private String TableName;//表格名称
    private String DateTime;//操作时间
    private String resultValue;//返回值
    private String ip;//ip地址
    private String  requestUrl;//请求地址
    private String result;//操作结果
    private  String ExString;//错误信息
 
    public CrmLogMessage() {
    }

3、定义切面类

/**
 * @ClassName SystemLogAspect
 * @Author Administrator
 * @Describe  定义切入面类
 */
@Aspect
@Component
public class SystemLogAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(LoggingAspect.class);


    /**
     * 注解Pointcut切入点
     * 定义出一个或一组方法,当执行这些方法时可产生通知
     * 指向你的切面类方法
     * 由于这里使用了自定义注解所以指向你的自定义注解
     */
    @Pointcut("@annotation(log.SystemCrmlog)")
    public void crmAspect() {
    }


    /**
     * 抛出异常后通知(@AfterThrowing):方法抛出异常退出时执行的通知
     * 注意在这里不能使用ProceedingJoinPoint
     * 不然会报错ProceedingJoinPoint is only supported for around advice
     * throwing注解为错误信息
     *
     * @param joinPoint
     * @param ex
     */
    @AfterThrowing(value = "crmAspect()", throwing = "ex")
    public void afterThrowingMethod(JoinPoint joinPoint, Exception ex) throws Exception {
        HttpServletRequest httpServletRequest = getHttpServletRequest();
        //获取管理员用户信息\
        WebUtil webUtil = new WebUtil();
        Map<String, Object> user = webUtil.getUser(httpServletRequest);
        CrmLogMessage log = new CrmLogMessage();
        //获取需要的信息
        String context = getServiceMthodDescription(joinPoint);
        String usr_name = "";
        String rolename = "";
        if (user != null) {
            usr_name = user.get("usr_name").toString();
            rolename = user.get("rolename").toString();
        }
        //管理员姓名
        log.setUserName(usr_name);
        //角色名
        log.setUserRole(rolename);
        //日志信息
        log.setContent(usr_name + context);
        //设置参数集合
        log.setRemarks(getServiceMthodParams(joinPoint));
        //设置表名
        log.setTableName(getServiceMthodTableName(joinPoint));
        //操作时间
        SimpleDateFormat sif = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        log.setDateTime(sif.format(new Date()));
        //设置ip地址
        log.setIp(httpServletRequest.getRemoteAddr());
        //设置请求地址
        log.setRequestUrl(httpServletRequest.getRequestURI());
        //执行结果
        log.setResult("执行失败");
        //错误信息
        log.setExString(ex.getMessage());
        //将数据保存到数据库
        //TODO: 2023-06-04   保存到数据库
        LOGGER.info("操作对象:" + log);
    }


    /**
     * 返回后通知(@AfterReturning):在某连接点(joinpoint)
     * 正常完成后执行的通知:例如,一个方法没有抛出任何异常,正常返回
     * 方法执行完毕之后
     * 注意在这里不能使用ProceedingJoinPoint
     * 不然会报错ProceedingJoinPoint is only supported for around advice
     * crmAspect()指向需要控制的方法
     * returning  注解返回值
     *
     * @param joinPoint
     * @param returnValue 返回值
     * @throws Exception
     */
    @AfterReturning(value = "crmAspect()", returning = "returnValue")
    public void doCrmLog(JoinPoint joinPoint, Object returnValue) throws Exception {
        HttpServletRequest httpServletRequest = getHttpServletRequest();
        //获取管理员用户信息
        WebUtil webUtil = new WebUtil();
        Map<String, Object> user = webUtil.getUser(httpServletRequest);
        CrmLogMessage log = new CrmLogMessage();
        String context = getServiceMthodDescription(joinPoint);

        String usr_name = "";
        String rolename = "";
        if (user != null) {
            usr_name = user.get("usr_name").toString();
            rolename = user.get("rolename").toString();
        }
        //管理员姓名
        log.setUserName(usr_name);
        //角色名
        log.setUserRole(rolename);
        //日志信息
        log.setContent(usr_name + context);
        //设置参数集合
        log.setRemarks(getServiceMthodParams(joinPoint));
        //设置表名
        log.setTableName(getServiceMthodTableName(joinPoint));
        //操作时间
        SimpleDateFormat sif = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        log.setDateTime(sif.format(new Date()));
        //设置ip地址
        log.setIp(httpServletRequest.getRemoteAddr());
        //设置请求地址
        log.setRequestUrl(httpServletRequest.getRequestURI());
        System.out.println(returnValue);
        if (returnValue != null) {
            if (returnValue instanceof List) {
                List ls = (List) returnValue;
                if (ls.size() > 0) {
                    log.setResult("执行成功");
                } else {
                    log.setResult("执行成功");
                }
            } else if (returnValue instanceof Boolean) {
                Boolean falg = (Boolean) returnValue;
                if (falg) {
                    log.setResult("执行成功");
                } else {
                    log.setResult("执行失败");
                }
            } else if (returnValue instanceof Integer) {
                Integer i = (Integer) returnValue;
                if (i > 0) {
                    log.setResult("执行成功");
                } else {
                    log.setResult("执行失败");
                }
            } else {
                log.setResult("执行成功");
            }

        }
        //将数据保存到数据库
        //TODO: 2023-06-04   保存到数据库
        LOGGER.info("操作对象:" + log);
    }


    /**
     * 获取自定义注解里的表名
     *
     * @param joinPoint
     * @return 返回注解里的表名字
     * @throws Exception
     */
    private String getServiceMthodTableName(JoinPoint joinPoint)
            throws Exception {
        //类名
        String targetName = joinPoint.getTarget().getClass().getName();
        //方法名
        String methodName = joinPoint.getSignature().getName();
        //参数
        Object[] arguments = joinPoint.getArgs();
        //通过反射获取示例对象
        Class targetClass = Class.forName(targetName);
        //通过实例对象方法数组
        Method[] methods = targetClass.getMethods();
        //表名
        String tableName = "";
        for (Method method : methods) {
            //判断方法名是不是一样
            if (method.getName().equals(methodName)) {
                //对比参数数组的长度
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    //获取注解里的表名
                    tableName = method.getAnnotation(SystemCrmlog.class).tableName();
                    break;
                }
            }
        }
        return tableName;
    }

    /**
     * 获取自定义注解里的日志描述
     *
     * @param joinPoint
     * @return 返回注解里面的日志描述
     * @throws Exception
     */
    private String getServiceMthodDescription(JoinPoint joinPoint)
            throws Exception {
        //类名
        String targetName = joinPoint.getTarget().getClass().getName();
        //方法名
        String methodName = joinPoint.getSignature().getName();
        //参数
        Object[] arguments = joinPoint.getArgs();
        //通过反射获取示例对象
        Class targetClass = Class.forName(targetName);
        //通过实例对象方法数组
        Method[] methods = targetClass.getMethods();
        String description = "";
        for (Method method : methods) {
            //判断方法名是不是一样
            if (method.getName().equals(methodName)) {
                //对比参数数组的长度
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    //获取注解里的日志信息
                    description = method.getAnnotation(SystemCrmlog.class).description();
                    break;
                }
            }
        }
        return description;
    }

    /**
     * 获取json格式的参数用于存储到数据库中
     *
     * @param joinPoint
     * @return
     * @throws Exception
     */
    private String getServiceMthodParams(JoinPoint joinPoint)
            throws Exception {
        Object[] arguments = joinPoint.getArgs();
        ObjectMapper om = new ObjectMapper();
        System.out.println();
        String parma = JSON.toJSONString(arguments);
        System.out.println(parma);
        Object o =JSONPath.read(parma,"$.a.b");
        System.out.println(o);
        List<JSONObject> hwList = (List<JSONObject>) JSONPath.read(parma, "$.deptList");
        System.out.println("hwList:" + hwList);
        String re = om.writeValueAsString(arguments);
        System.out.println(re);
        return re;
    }

    /**
     * 获取当前的request
     * 这里如果报空指针异常是因为单独使用spring获取request
     * 需要在配置文件里添加监听
     * <listener>
     * <listener-class>
     * org.springframework.web.context.request.RequestContextListener
     * </listener-class>
     * </listener>
     *
     * @return
     */
    public HttpServletRequest getHttpServletRequest() {
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();
        return request;
    }

4、通过JsonPath获取json指定节点字段值

       String parma = JSON.toJSONString(arguments);
        System.out.println(parma);
        Object o =JSONPath.read(parma,"$.a.b");
        System.out.println(o);

如果下级节点是数组则可使用如下方式获取

 List<JSONObject> hwList = (List<JSONObject>) JSONPath.read(parma, "$.deptList");
        System.out.println("hwList:" + hwList);
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容