当前位置 : 主页 > 编程语言 > java >

Springboot AOP日志

来源:互联网 收集:自由互联 发布时间:2023-12-16
创建一个枚举的业务类型对象 public enum BusinessType { /** * 新增 * */ INSERT("新增"), /** * 更新 * */ UPDATE("更新"), /** * 删除 * */ DELETE("删除"); /** * 业务类型 * */ public String type; BusinessType(String t
  1. 创建一个枚举的业务类型对象
public enum  BusinessType {
    /**
     * 新增
     *  */
    INSERT("新增"),
    /**
     * 更新
     *  */
    UPDATE("更新"),
    /**
     * 删除
     *  */
    DELETE("删除");
    /**
     * 业务类型
     *  */
    public String type;

    BusinessType(String type) {
        this.type = type;
    }
}
  1. 创建一个枚举的业务类型对象

这段代码定义了一个名为BookLog的Java注解,主要用于方法上。它包含两个元素:titlebusinessType。其中,title用于提供描述信息,而businessType则用于指定业务分类,其值来源于BusinessType枚举。该注解被设计为在运行时可见,可被包含在javadoc中,且如果一个类被这样的注解标注,其子类会继承这个注解。

import com.ds.common.enums.BusinessType;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface BookLog {
    /**
     * 描述
     */
    String title();

    /**
     * 业务分类
     */
    BusinessType businessType();
}
  1. 创建LogAspect切面类
    使用 Spring AOP(面向切面编程)的切面(Aspect)类,主要用于在指定注解 @BookLog 标记的方法上执行日志记录操作。这是一种典型的日志切面,可以在方法执行后记录相关信息,也能在方法抛出异常时记录异常信息。
    让我详细解释一下这段代码的关键部分:
  1. @Aspect 注解: 表示这是一个切面类,它包含了一些横切关注点(cross-cutting concerns),即在应用中多个模块中共享的功能。这里的关注点是日志记录。
  2. @Component 注解: 将这个类声明为一个 Spring 组件,以便 Spring 容器能够管理它。
  3. @Pointcut 注解: 定义切点,即指定在哪些方法上执行切面逻辑。在这里,切点是所有被 @BookLog 注解标记的方法。
  4. @AfterReturning 注解: 定义一个后置通知,在切点方法成功执行后执行。这里的 doAfterReturning 方法用于在方法返回后执行日志记录操作,并将日志信息插入数据库。
  5. @AfterThrowing 注解: 定义一个异常通知,在切点方法抛出异常后执行。这里的 doAfterThrowing 方法用于在方法抛出异常时执行日志记录操作,并将异常信息插入数据库。
  6. JoinPoint 参数: 表示连接点,即被拦截的方法。通过 JoinPoint 可以获取方法名、参数等信息。
  7. @Autowired 注解: 将 SysLogMapper 注入到切面类中,以便在日志记录时可以访问数据库。
  8. handleLog 方法: 一个私有方法,用于创建 SysLog 对象并设置相关信息,如业务类型、类名、方法名、参数值等。

总体来说,这段代码使用了 Spring AOP 技术,通过切面实现了在被 @BookLog 注解标记的方法上进行日志记录的功能。这种方式可以在不修改原有业务逻辑代码的情况下,方便地添加和管理一些横切关注点,如日志记录、性能监控等。

@Aspect
@Component
public class LogAspect {

    @Autowired
    private SysLogMapper sysLogMapper;

    /**
     * 切点
     */
    @Pointcut(value = "@annotation(com.ds.common.annotation.BookLog)")
    public void logPointCut(){

    }

    /**
     * 方法返回后的通知
     */
    @AfterReturning(value = "logPointCut() && @annotation(bookLog)", returning = "obj")
    public void doAfterReturning(JoinPoint joinPoint, BookLog bookLog, Object obj) {
        SysLog sysLog = handleLog(joinPoint, bookLog);
        sysLogMapper.insert(sysLog);
    }

    /**
     * 抛出异常后的通知
     */
    @AfterThrowing(value = "logPointCut() && @annotation(bookLog)", throwing = "e")
    private void doAfterThrowing(JoinPoint joinPoint, BookLog bookLog, Exception e) {
        SysLog sysLog = handleLog(joinPoint,bookLog);
        StringWriter stackTraceWriter = new StringWriter();
        //异常堆栈信息
        e.printStackTrace(new PrintWriter(stackTraceWriter, true));
        sysLog.setStackTrace(stackTraceWriter.toString());
        //错误信息
        String errMsg = e.getMessage();
        sysLog.setErrMsg(errMsg);
        //异常类型
        String exceptionName = e.toString();
        sysLog.setExceptionName(exceptionName);
        sysLogMapper.insert(sysLog);
    }


    private SysLog handleLog(JoinPoint joinPoint,BookLog bookLog){
        SysLog sysLog = new SysLog();
        //设置业务类型
        sysLog.setTitle(bookLog.title());
        sysLog.setBusinessType(bookLog.businessType().type);
        //获取代理类
        String className = joinPoint.getTarget().getClass().getName();
        sysLog.setClassName(className);
        //获取方法名称
        String methodName = joinPoint.getSignature().getName();
        sysLog.setMethodName(methodName);
        //获取包名称
        String packageName = joinPoint.getSignature().getDeclaringTypeName();
        sysLog.setPackageName(packageName);
        // 参数值
        Object[] argsValue = Arrays.stream(joinPoint.getArgs()).toArray(Object[]::new);
        sysLog.setArgsValue(StringUtils.join(argsValue));
        // 参数名
        String[] argsNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
        sysLog.setArgsName(StringUtils.join(argsNames));
        return sysLog;
    }
}
  1. 加载bean到Spring容器并开启Aspect
@Slf4j
@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)  //开启aspect
public class BookApplication {
  1. controller中使用

@BookLog(title = "添加栏目",businessType = BusinessType.INSERT),添加了@BookLog的注解的,会自动记录日志

@BookLog(title = "添加栏目",businessType = BusinessType.INSERT)
@PostMapping("/add")
@ResponseBody
public Result add(@RequestBody @Validated Article article, BindingResult bindingResult){
    if (bindingResult.hasErrors()){
        return Result.failure(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage());
    }
    article.setChannelName(channelService.detail(article.getChannelId()).getName());
    boolean flag = articleService.save(article);
    return Result.success(flag);
}


网友评论