SpringAOP记录日志

前几天接到临时需求,要求记录下每个人在几点对什么模块进行了什么操作。首先听到这个需求,我第一想到了就是用spring的AOP来实现,然后经过了一下午的调试弄出来了,在这里记录下在写代码是遇到的问题,以及解决方法。

首先明确需求,既然是要记录下每个人的操作,那肯定是需要将这些操作持久化的。于是创建了相应的表,实体类接下来开始写切面。

@Aspect
@Component
public class LogAopAspect {

   private Logger logger = LoggerFactory.getLogger (this.getClass ());
    
    @Autowired
    private LogServiceImpl logservice;

    @Pointcut("execution(* com.baidu.fpd.loanmis.controller..*.*(..))")
    private void controllerAspect () {} // 定义一个切入点,说明我要切controller这个包下面的类
    
    @Around("controllerAspect()") // 定义一个环绕通知
    public Object around (ProceedingJoinPoint pjp) throws Throwable {
        logger.info ("进入环绕通知");

        LoanLogEntity ll = new LoanLogEntity ();// 要入库的实体类

        // 拦截的实体类,就是当前正在执行的controller
        Object target = pjp.getTarget ();
        // 拦截的方法名称。当前正在执行的方法
        String methodName = pjp.getSignature ().getName ();

        // 拦截的放参数类型
        Signature sig = pjp.getSignature ();
        MethodSignature msig = null;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException ("该注解只能用于方法");
        }
        msig = (MethodSignature) sig;
        Class[] parameterTypes = msig.getMethod ().getParameterTypes ();

        Object object = null;
        // 获得被拦截的方法
        Method method = null;
        try {
            method = target.getClass ().getMethod (methodName, parameterTypes);
        } catch (NoSuchMethodException e1) {
            e1.printStackTrace ();
        }
        
        if (null != method) {
            // 判断是否包含自定义的注解,说明一下这里的SystemLog就是我自己自定义的注解
            if (method.isAnnotationPresent (SystemLog.class)) {
                SystemLog systemlog = method.getAnnotation (SystemLog.class);
                if (!"".equals (systemlog.methods ())) {
                    // 拦截的方法参数
                    Object[] args = pjp.getArgs ();
                    if (systemlog.methods ().equals ("修改状态")) {
                        // dosomething
                    }
                }
            }
        }
        try {
            object = pjp.proceed ();
            ll.setResult ("执行成功!");
            logservice.saveLog (ll);
        } catch (Throwable e) {
            ll.setResult ("执行失败!");
            logservice.saveLog (ll);
        }
       } else { // 没有包含注解
                object = pjp.proceed ();
               }
        } else { // 不需要拦截直接执行
            object = pjp.proceed ();
        }
        logger.info ("退出环绕通知");
        return object;
    }
}
import java.lang.annotation.*;

@Target ({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemLog {
    // 这是我自定义的注解,需要记录的地方就在方法上面加上就是
    String module ()  default "";
    String methods ()  default "";
}

xml里加上

<aop:aspectj-autoproxy proxy-target-class="true" /> 开启aop

这基本上就完成了aop记录业务日志的操作

说一下遇到的问题吧,

一、首先就是动态的记录每个操作具体的内容,比如状态由XX变成了XX

这里可以看下这行代码 Object[] args = pjp.getArgs ();其实传过来的参数都在args里了,具体可以自己拿里面的参数值做一些业务判断

二、aop记录日志的时候打印了两遍日志,也就是两次进入环绕通知方法,网上查了下原因,是因为项目代码里有两个地方开启了代理,

@Component因为交给了spring管理<bean id="LogAopAspect" class="com.baidu.fpd.loanmis.aop.LogAopAspect"/>

后来把这段注释掉就可以了。

参考:http://stackoverflow.com/questions/7900905/spring-aop-advice-is-called-twice

最后这次尝试了写了一下枚举类,因为之前一直都没用过,这次用后发现真的太方便了,省了巨多代码这面这段就是

public enum UnionConfigStatus {
    //状态 1新建 11已发布 12预发布 21已关闭 22 预关闭 31已删除

    UC_NEW (1, "新建"),
    UC_RELEASE (11, "已发布"),
    UC_PRERELEASE (12, "预发布"),
    UC_SHUTDOWN (21, "已关闭"),
    UC_PRESHUTDOWN (22, "预关闭"),
    UC_DELETE (31, "已删除");

    private Integer status;
    private String desc;

    private UnionConfigStatus (Integer status, String desc) {
        this.status = status;
        this.desc = desc;
    }

    public static String getDesc (Integer key) {
        for (UnionConfigStatus ucs : UnionConfigStatus.values ()) {
            if (ucs.getStatus ().equals (key)) {
                return ucs.getDesc ();
            }
        }
        return "-";
    }

    public Integer getStatus () {
        return status;
    }

    public String getDesc () {
        return desc;
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值