返回顶部

java使用注解实现系统日志记录

不论在神魔类型的项目中,日志系统绝对是一个不可少的存在,那么,怎末用一个最简便的方式来实现日志在数据库中的存储呢??最近在项目中正好负责了日志模块的实现,就简单记录一下。

我在这个项目中使用的是aop自定义注解的方式,大致步骤如下:

1.第一步,首先需要先定义一个注解类,来实现部分方法介绍信息的传递和切入点的切入时机。

复制代码
package com.cms.common.annotation;
 
 
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * 操作日志注解类
 * 请填上日志描述:desc
 */
@Target({ElementType.PARAMETER, ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
public @interface ControllerOptLog {
    /**
     * 日志描述
     * @return
     */
    String desc() default "";
}
复制代码

spring自定义注解,不多解释,其中属性desc是为切面传输必要参数的。

2.第二步,需要定义一个切面类,并在切面类中编写aop切入的前后通知等方法。

复制代码
package com.cms.common.annotation;
 
import com.cms.common.utils.IPUtil;
import com.cms.common.utils.security.AccountShiroUtil;
import com.cms.common.utils.security.UserShiroUtil;
import com.cms.entity.company.Account;
import com.cms.entity.system.log.ErrorLog;
import com.cms.entity.system.log.OperateLog;
import com.cms.entity.system.users.Users;
import com.cms.service.system.log.ErrorLogService;
import com.cms.service.system.log.OptLogService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
 
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
 
@Aspect
@Component
@Order(1)// Order值越小优先被加载
public class OperateAspect {
 
    private final Log logger = LogFactory.getLog(OperateAspect.class);
 
    private Boolean recordOptLog = true;
 
 
    private OperateLog operateLog;
 
 
    @Autowired
    OptLogService operateLogService;
 
    @Autowired
    ErrorLogService errorLogService;
 
    @Before(value = "@annotation(com.cms.common.annotation.ControllerOptLog)")
    public void beforeAdvice(JoinPoint joinPoint) throws Throwable {
        Object[] args = joinPoint.getArgs();
        if (recordOptLog) {
            try {
                operateLog = new OperateLog();
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                        .getRequest();
                String ip = IPUtil.getIpAddr(request);
                MethodSignature signature = (MethodSignature) joinPoint.getSignature();
                Method method = signature.getMethod();
                Users currentUser= UserShiroUtil.getCurrentUser();
                ControllerOptLog controllerOptLog = method.getAnnotation(ControllerOptLog.class);
                String desc = controllerOptLog.desc();
                RequestMapping requestMappingAnnotation = joinPoint.getTarget().getClass().getAnnotation(RequestMapping.class);
                String url = request.getRequestURI();
                //添加记录内容
                operateLog.setIp(ip);
                operateLog.setUserName(currentUser.getName());
                operateLog.setParams(method.getParameters().toString());
                operateLog.setUserCode(currentUser.getCode());
                operateLog.setUrl(url);
                operateLog.setDesc(desc);
                operateLog.setBeginTime(new Date().toLocaleString());
 
            } catch (Throwable e) {
                logger.error("记录操作日志错误", e);
            }
        }
    }
 
 
    @AfterReturning(value = "@annotation(com.cms.common.annotation.ControllerOptLog)")
    public void afterAdvice(JoinPoint joinPoint) throws Throwable {
        if (recordOptLog) {
            try {
                operateLog.setEndTime(new Date().toLocaleString());
                operateLogService.log(operateLog);
            } catch (Throwable e) {
                logger.error("记录操作日志错误", e);
            }
        }
    }
 
    @AfterThrowing(value = "@annotation(com.cms.common.annotation.ControllerOptLog)",throwing = "e")
    public void erroeAdvice(JoinPoint joinPoint,Throwable e){
 
        Object[] args = joinPoint.getArgs();
        ErrorLog errorLog = new ErrorLog();
        if (recordOptLog) {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                    .getRequest();
            String ip = IPUtil.getIpAddr(request);
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            Users currentUser = UserShiroUtil.getCurrentUser();
            ControllerOptLog controllerOptLog = method.getAnnotation(ControllerOptLog.class);
            String desc = controllerOptLog.desc();
            RequestMapping requestMappingAnnotation = joinPoint.getTarget().getClass().getAnnotation(RequestMapping.class);
            String url = request.getRequestURI();
 
            errorLog.setUserCode(currentUser.getCode());
            errorLog.setUserName(currentUser.getName());
            errorLog.setParams(method.getParameters().toString());
            errorLog.setIp(ip);
            errorLog.setDesc(desc);
            errorLog.setContent(e.toString());
            errorLog.setUrl(url);
            errorLog.setCurrTime(new Date().toLocaleString());
 
            errorLogService.saveErrorAndOpt(errorLog);
        }
    }
}
复制代码

需要注意的是,在这个切面类中所有的通知方法切入的位置都是指定为执行自定义注解时

value = "@annotation(com.cms.common.annotation.ControllerOptLog)"

在执行到切面方法 的时候可以通过 JoinPoint 对象获取一些请求上的参数,比如request,parms等等,同时因为使用的是自定义注解,所以可以通过

method.getAnnotation();

方法获取到标注注解的时候存入的操作介绍,最后把这些需要的参数封装到日志对象中,存入数据库或者指定位置中。

在需要切入的地方需要标上自己定义的注解,我的如下:

复制代码
/**
     * 跳转到发件箱
     * @return
     */
    @ControllerOptLog(desc = "发件箱跳转")
    @RequestMapping("tohairlist")
    public String tolist(Model model) {
        model.addAttribute("permitBtn", getPermitBtn(Const.RESOURCES_TYPE_BUTTON));
        model.addAttribute("tableBtn", getPermitBtn(Const.RESOURCES_TYPE_FUNCTION));
        return "/system/message/Hairbox/tolist";
    }
复制代码

例子很好,有很多可以学习的地方哦~
原文链接:https://blog.csdn.net/W_DongQiang/article/details/80158382

posted @   fen斗  阅读(102)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
历史上的今天:
2020-03-30 登录为什么登陆什么都要验证码?验证码有什么用?没有验证码之后会有什么危害
点击右上角即可分享
微信分享提示