SpringBoot中使用AOP(注解版)进行日志管理

1、介绍:

我们都知道AOP是Spring中的重要组成部分,作用就是在不改变业务代码的情况下对业务进行扩展,具体表现为,登录认证、日志管理、事务管理、用户信息追踪等等。而AOP切面类中可以实现的通知有: 前置通知、后置通知、异常通知、返回通知、环绕通知(最为重要,可以控制方法何时进行调用) 在本文,我将详细的介绍在Sprinboot中如何使用注解对用户的日志进行管理。

AOP的底层原理,这里提一嘴,AOP的底层原理就是动态代理,JDK动态代理和CGLIB动态代理,后面我会出Spring系列的博客讲解Spring IOC的原理和 SpringAOP的原理。

2、具体应用

  • 第一步: 引入aop的starter
    <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-aop</artifactId>
       </dependency>
  • 第二步: yml文件中开启aop功能
    在这里插入图片描述
  • 第三步: 配置aop包的目录结构
    在这里插入图片描述
  • 第五步: 编码各个文件
    1、SysLog实体类:
@ApiModel("日志的实体类")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SysLog  implements Serializable {
    @ApiModelProperty(value = "创建的id",example = "0")
    private String id;

    @ApiModelProperty(value = "操作")
    private String operation;

    @ApiModelProperty(value = "方法名")
    private String method;

    @ApiModelProperty(value = "参数")
    private String params;

    @ApiModelProperty(value = "ip地址")
    private String ip;

    @ApiModelProperty(value = "报错信息,当无报错的时候这个信息为空")
    private String errorMessage;

    @ApiModelProperty(value = "用户操作返回的信息")
    private String responseMessage;

    @ApiModelProperty(value = "创建时间")
    private  String createTime;
}

2、SysLogMapper:

@Mapper
public interface SysLogMapper {

    @Insert("insert into t_log(operation,method,params,ip,error_message,response_message)" +
            "values(#{operation},#{method},#{params},#{ip},#{errorMessage},#{responseMessage})")
    public void insertLog(SysLog sysLog);
}

3、 SysLogService、和 SysLogServiceImpl

public interface SysLogService {
    /**
     * 插入日志记录
     * @param sysLog
     */
    public void insertLog(SysLog sysLog);
}

@Service
public class SysLogServiceImpl implements SysLogService {

    @Autowired
    private SysLogMapper sysLogMapper;

    @Override
    public void insertLog(SysLog sysLog) {
        sysLogMapper.insertLog(sysLog);
    }
}

4、annotation --MyLog 注解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyLog {
    String value() default "";
}

5、切面类,这些只写出了异常通知、返回通知、环绕通知、其他的通知还有前置通知、后置通知就不一一列出来了:

@Aspect
@Component
public class SysLogAspect {

    @Autowired
    private SysLogService sysLogService;

    /**
     *  切入点表达式
     */
    @Pointcut("@annotation(com.justreading.onePanda.aop.annotation.MyLog)")
    public void  logPointCut(){};


    /**
     * 报错异常通知
     */
    @AfterThrowing(value = "logPointCut()",throwing = "e")
    public void  saveErrorLog(JoinPoint joinPoint,Exception e){
         SysLog sysLog  = new SysLog();
         MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
         Method method = methodSignature.getMethod();

         MyLog myLog = method.getAnnotation(MyLog.class);
         String operation = myLog.value();
         String methodName = method.getName();
         String className = joinPoint.getTarget().getClass().getName();

         ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
         HttpServletRequest request = requestAttributes.getRequest();

         Object[] args = joinPoint.getArgs();

         sysLog.setOperation(operation);
         sysLog.setMethod(className + "." + methodName);
         sysLog.setIp(request.getRemoteAddr());
         sysLog.setParams(JSON.toJSONString(args));
         sysLog.setErrorMessage("报错:" + e);

         //插入日志记录
         sysLogService.insertLog(sysLog);
    }

    /**
     * 切面 配置通知,返回的消息,正常的不切了,不然消息太多了
     */
    @AfterReturning(value = "logPointCut()",returning = "ret")
    public void saveReturnLog(JoinPoint joinPoint,Object ret){
        SysLog sysLog  = new SysLog();

        //获取切入点所在的方法
        MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();
        Method method = methodSignature.getMethod();

        //获取操作
        MyLog myLog = method.getAnnotation(MyLog.class);
        if(myLog != null){
            String value = myLog.value();
            sysLog.setOperation(value);
        }

        //获取请求的类名
        String className = joinPoint.getTarget().getClass().getName();

        //获取请求的方法名
        String methodName = method.getName();
        sysLog.setMethod(className + "." + methodName);

        //请求的参数
        Object[] args = joinPoint.getArgs();
        for(Object arg : args){
        }

        //将参数所在的数组转换成json
        String params = JSON.toJSONString(args);
        sysLog.setParams(params);

         //获取用户的ip地址
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        sysLog.setIp(request.getRemoteAddr());

        //设置返回的信息
        sysLog.setResponseMessage("返回信息:" + JSON.toJSONString(ret));

        //插入日志记录
        sysLogService.insertLog(sysLog);
    }

    @Around(value = "logPointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕之前");

        //被切入方法的执行
        Object proceed = proceedingJoinPoint.proceed();

        System.out.println("环绕之后");
        return proceed;
    }

}

6、将该注解应用到相对应的方法上:
在这里插入图片描述

三、总结:

AOP的使用相对来说还是比较简单的、特别是注解版的AOP更加人性化只要通过一个注解就可以对类中的方法进行切入,相对xml方式更加的方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值