传统springmvc项目使用aop(记录日志功能)

1、spring-mvc.xml配置
<bean id="operationLogAspect" class="com.xxx.aop.OperationLogAspect" />
2、注解类
package com.xxx.aop;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 操作日志
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperationLog {
    /**
     * 要操作的资源
     *
     * @return 资源
     */
    OperationType value();

    /**
     * 日志类型
     */
    enum OperationType {
        ADD,                // 发布
        UPDATE_STATUS_ON,   // 上架
        UPDATE_STATUS_OFF,  // 下架
        EDIT,               // 编辑
        UPGRADE,            // 更新
    }
}
3、aop类
package com.xxx.aop;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
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.*;

@Aspect  // 标注为一个切面
@Component
@EnableAspectJAutoProxy(proxyTargetClass = true) // 开启注解版的aop功能,也可以直接在xml中配置<aop:aspectj-autoproxy />,在xml中配置需要添加相应的xmlns
public class OperationLogAspect {
    protected static Logger logger = LoggerFactory.getLogger(OperationLogAspect.class);

    @Pointcut("@annotation(com.xxx.OperationLog)")
    private void operationLog() {
    }

    /**
     * 被代理方法处理完后执行
     *
     * @param joinPoint 连接点。可以从中取到注解的的参数以及被代理方法的参数
     * @param result 被代理方法的返回值,可以定义成自己想要的类型
     */
    @AfterReturning(pointcut = "operationLog()", returning = "result")
    public void after(JoinPoint joinPoint, boolean result) {
        if (!result) return;  // 这里因为定义的返回值类型是boolean,所以被代理方法返回false的情况就没有记录

        // 获取注解
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        final OperationLog annotation = method.getAnnotation(OperationLog.class);
        if (annotation != null) {
            System.out.println(annotation.value());  // 注解中的value值
        }

        // 获取被代理方法参数
        // 原先是想要获取接口请求参数,但是被代理方法已经从request中取出了请求参数,而request流只能单次读取。所以after方法中是取不到请求参数的
        // args数组的内容就是被代理方法的参数
        final Object[] args = joinPoint.getArgs();
        // params就是被代理方法add的第一个参数
        Map params = (Map) args[0];
        // response就是被代理方法add的第二个参数
        HttpServletResponse response = (HttpServletResponse) args[1];


        // 还可以取到例如保存再session中的用户信息
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            String userID = (String) request.getSession().getAttribute("userid");
    }

    /**
     * 如果after方法出错,在这里可以捕获
     *
     * @param jp JoinPoint
     * @param e  RuntimeException
     */
    @AfterThrowing(pointcut = "operationLog()", throwing = "e")
    public void afterThrowing(JoinPoint jp, RuntimeException e) {
        logger.error(jp.getSignature().getName() + "方法发生异常," + e);
    }
}
 4,被代理方法
@OperationLog(OperationLog.OperationType.ADD)
    public boolean add(@Valid @RequestBody Map<String, Object> params, HttpServletResponse response) {

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值