第一步引入必要的依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.3.15</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.2</version>
        </dependency>

第二步创建自定义日志注解类

实际上可以对注解添加一个业务类型参数表示日志的类型:新、删、改、查

package com.example.aop.log.annotion;

import java.lang.annotation.*;

/**
 * @author zhr_java@163.com
 * @date 2022/3/29 20:56
 */
@Inherited
@Target({ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface LogNotice {}

第三步切面设计,扫描上面的注解

此处实际上还可以根据注解里面的参数来判断业务日志的类型:新、删、改、查

package com.example.aop.log.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhr_java@163.com
 * @date 2022/3/29 20:59
 */
@Aspect
@Component
public class LogAspect {

//此处扫描的是你的注解,当然也可以扫描全部的包,但是不利于后期的扩展,因为后期别人创建的包不在扫描范围内那就可能导致日志记不到
  @Pointcut("@annotation(com.example.aop.log.annotion.LogNotice)")
  public void doLog() {}

  @Around("doLog()")
  public Object insertLog(ProceedingJoinPoint joinPoint) throws Throwable {
    Object object = joinPoint.proceed();
    try {
      HashMap paramsMap;
      Signature signature = joinPoint.getSignature();
      Method method = ((MethodSignature) signature).getMethod();
      String methodName = method.getName();
      String className = method.getDeclaringClass().getName();
      paramsMap = (HashMap) getParams(joinPoint, method);
      // 打印日志,可以记录到数据库的日志表里面,等到有客户反馈的时候好去查询日志
      System.out.println(
          "methodName: " + methodName + "; className: " + className + "; paramsMap:" + paramsMap);
      // 也可以记录请求当前接口耗费的时间
    } catch (Exception e) {
      // 如果在日志记录的过程中出现问题,那么要处理一下异常,不要直接抛出,此处做成消息队列通知或者打印日志
    }

    // 此处要进行返回代理的对象,如果没有返回的话,前端是收不到数据的
    return object;
  }

  private Map<String, Object> getParams(ProceedingJoinPoint joinPoint, Method method) {
    // get parameter names
    String[] parameterNames = new DefaultParameterNameDiscoverer().getParameterNames(method);
    Object[] args = joinPoint.getArgs();
    Map<String, Object> params = new HashMap<>(8);
    if (parameterNames != null && parameterNames.length != 0) {
      for (int i = 0; i < parameterNames.length; i++) {
        params.put(parameterNames[i], args[i]);
      }
    }
    return params;
  }
}

第四步把自定义的注解放到你的接口上面

package com.example.demo.controller;

import com.example.aop.log.annotion.LogNotice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author zhr_java@163.com
 * @date 2022/3/29 20:50
 */
@RestController
@RequestMapping("/person")
public class PersonController {

  //在此处加上你自定义的注解(@LogNotice)
  @LogNotice
  @GetMapping("get_person")
  public String getPerson(Integer numbers) {
    return "123";
  }
}

第五步测试

在这里插入图片描述

在这里插入图片描述

关注我的公众号SpaceObj 领取idea系列激活码

posted on 2023-05-10 18:25  张伯灵  阅读(108)  评论(0)    收藏  举报