springboot 使用AOP日志拦截实现

借助springAOP功能,我们可以将AOP应用至全局异常处理,全局请求拦截等,本篇文章的核心功能就是使用AOP实现日志记录,比如哪些用户进行了哪些操作,对于一个成功的项目这是必须记录的,故知识追寻者这边给出一个简单模型应用;

二 定义枚举

枚举定义的类型就是实现日志的哪些操作,如下所示,有些是登陆日志,有些是增删改查日志,不同的系统可以定义不同的日志,读者可以自由选择;

public enum LogEnum {

    UNOPERATE(0,"未定义操作"),
    SELECT(1,"查询"),
    INSERT(2,"添加"),
    UPDATE(3,"更新"),
    DELETE(4,"删除"),
    EXPORT(5,"excel导出"),
    LOGIN(6,"登陆"),
    LOGOUT(7,"登出"),
    ;

    LogEnum( Integer code, String operate) {
        this.operate = operate;
        this.code = code;
    }

    LogEnum(){

    }

    // 操作
    private String operate;
    // 操作码
    private Integer code;

    public String getOperate() {
        return operate;
    }

    public void setOperate(String operate) {
        this.operate = operate;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }
}
复制代码

三 注解

使用注解的目的就是在哪些方法上使用注解,也就是标记这属于哪些操作,通过注解操作类型结合已经定义的枚举就可以简单的实现哪些方法上进行了哪些操作;

@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MonitorLog {

    /* *
     * @Author lsc
     * <p>日志内容 </p>
     * @Param []
     * @Return java.lang.String
     */
    String value() default "";

    /* *
     * @Author lsc
     * <p>日志操作类型 </p>
     * @Param []
     * @Return int
     */
    LogEnum operateType() default LogEnum.UNOPERATE;


}
复制代码

四 AOP切面

将注解设置为切点。将切点织入切面后使用环绕通知增强已经被注解标注的方法,此时就可以获得所有的注解操作,然后将日志记录入库,就可以简单实现用户的日志操作监控,当前提是在AOP中获得用户名,常见的shiro框架就有getSubject的方法获得用户名,当然根据不同的读者使用的技术不同进行获取,知识追寻者这边为了简单实现功能就没有使用一堆繁琐的方法去实现一个用户登陆认证系统;

/**
 * @Author lsc
 * <p>日志aop切面 </p>
 */

@Aspect
@Component
public class LogAsp {

    /* *
     * @Author lsc
     * <p> 设置切点</p>
     * @Param []
     * @Return void
     */
    @Pointcut("@annotation(com.zszxz.annotation.MonitorLog)")
    public void logPointCut() {

    }

    // 环绕通知
    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        // 开始时间
        LocalDateTime beginTime = LocalDateTime.now();
        // 执行方法
        Object result = point.proceed();
        // 结束时间
        LocalDateTime endTime = LocalDateTime.now();
        Duration duration = Duration.between(beginTime, endTime);
        // 操作时长
        long seconds = duration.getSeconds();
        // 保存日志
        saveLog(point,seconds);
        return result;
    }

    private void  saveLog(ProceedingJoinPoint point, long seconds){
        MethodSignature signature = (MethodSignature) point.getSignature();
        Method method = signature.getMethod();
        // 获得注解
        MonitorLog monitorLog = method.getAnnotation(MonitorLog.class);
        if (monitorLog!=null){
            // 获得操作类型
            LogEnum operateType = monitorLog.operateType();
            // 获得操作内容
            String value = monitorLog.value();
            System.out.printf("获得操作类型: %s , 获得操作内容: %s ",operateType.getCode(),value);

            //请求的参数
            Object[] args = point.getArgs();
            try{
                List<Object> objects = Arrays.asList(args);
                System.out.println(objects);
            }catch (Exception e){

            }

        }
    }
}
复制代码

五表现层

controller 所示,模拟进行查询用户操作的方法,并且在方法上标明注解这是个查询用户的方法,当访问此API时就会被AOP拦截;

/**
 * @Author lsc
 * <p> </p>
 */
@RestController
public class UserController {


    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @MonitorLog(value="查询用户",operateType = LogEnum.SELECT)
    @GetMapping("zszxz")
    public String getUser(String user){
        return "zszxz";
    }


}
复制代码

如果哪些不懂可以参照一下知识追寻者的源码(专栏说明或者公主号都要知识追寻者github地址),

原文 

https://juejin.im/post/5e97a492f265da47ca692d86

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » springboot 使用AOP日志拦截实现

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址