Springboot接口项目如何使用AOP记录日志

 更新时间:2020年06月03日 10:44:28   作者:画笔灬  
这篇文章主要介绍了Springboot接口项目如何使用AOP记录日志,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

一、 背景

一直想给项目构建一个统一的日志收集系统,先迈出第一步,构建一个日志收集类,用AOP实现无侵入日志收集

二、 环境

1.此随笔内容基于spring boot项目

2.数据库为mysql 5.7.9版本

3.jdk 版本为1.8

三、 说明

此版采用数据库存储,之后考虑使用elasticsearch等工具存储

四、 内容

1、构建日志采集实体类:BaseLogMessage

public class BaseLogMessage {
  private String serverIP;
  private String appName;
  private String method;
  private String type;
  private String userCode;
  private String uri;
  private String operationName;
  private String operationStatus;
  private long startTime;
  private Object parameter;
  private Object result;
  private int SpendTime;
 // 此处省略get、set
}

2、构建一个配置文件读取类,用于读取配置文件中的系统名称:SystemPropetiesUtil

@Configuration
public class SystemPropetiesUtil {
  @Value("${spring.application.name}")
  private String sysName;//系统名称<br>  // 此处省略get、set<br>}

3、新建一个AOP类,在控制器方法上作为切点,执行日志收集: LogAspect

@Aspect
@Component
public class LogAspect {
  @Autowired
  private SystemPropetiesUtil systemPropetiesUtil;
 
  //定义切点方法
  @Pointcut("execution(public * cq..campus.prevented.controller.*.*(..))")
  public void controllerLog() {
  }
 
  public static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);
 
  @Around("controllerLog()")
  public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    long startTime = System.currentTimeMillis();
    //获取当前请求对象
    ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    HttpServletRequest request = attributes.getRequest();
    //记录请求信息
    BaseLogMessage baseLogMessage = new BaseLogMessage();
    //1.获取到所有的参数值的数组
    Object[] args = joinPoint.getArgs();
    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    //2.获取到方法的所有参数名称的字符串数组
    String[] parameterNames = methodSignature.getParameterNames();
    Object result = joinPoint.proceed();
    Method method = methodSignature.getMethod();
    if (method.isAnnotationPresent(ApiOperation.class)) {
      ApiOperation apiOperation = method.getAnnotation(ApiOperation.class);
      baseLogMessage.setOperationName(apiOperation.value());
    }
    long endTime = System.currentTimeMillis();
    String urlStr = request.getRequestURL().toString();
    baseLogMessage.setUri(urlStr);
    baseLogMessage.setType("操作日志");
    baseLogMessage.setServerIP(getRemoteIP(request));
    baseLogMessage.setMethod(request.getMethod());
    baseLogMessage.setAppName(systemPropetiesUtil.getSysName());
    baseLogMessage.setResult(result);
    baseLogMessage.setParameter(getParameter(method, joinPoint.getArgs()));
    baseLogMessage.setSpendTime((int) (endTime - startTime));
    baseLogMessage.setStartTime(endTime);
    LOGGER.info("{}", JsonUtils.objectToJson(baseLogMessage));
    // 数据库存储操作
    return result;
  }
 
  /**
   * 异常返回通知,用于拦截异常日志信息 连接点抛出异常后执行
   *
   * @param joinPoint 切入点
   * @param e     异常信息
   */
  @AfterThrowing(pointcut = "controllerLog()", throwing = "e")
  public void saveExceptionLog(JoinPoint joinPoint, Throwable e) {
    long startTime = System.currentTimeMillis();
    if(null==kafkaClient){
      kafkaClient = KafkaProducerClient.getInstance(systemPropetiesUtil.getKafkaHost());
     //  redisClient= RedisClient.getInstance(systemPropetiesUtil.getReidsHost(), Integer.parseInt(systemPropetiesUtil.getRedisPort()), "");
    }
    // 获取RequestAttributes
    RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
    // 从获取RequestAttributes中获取HttpServletRequest的信息
    HttpServletRequest request = (HttpServletRequest) requestAttributes
        .resolveReference(RequestAttributes.REFERENCE_REQUEST);
    String urlStr = request.getRequestURL().toString();
    BaseLogMessage baseLogMessage = new BaseLogMessage();
    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    Method method = methodSignature.getMethod();
    StringBuffer strbuff = new StringBuffer();
    for (StackTraceElement stet : elements) {
      strbuff.append(stet + "\n");
    }
    String message = exceptionName + ":" + exceptionMessage + strbuff.toString();
    try {
      Object[] args = joinPoint.getArgs();
      String[] parameterNames = methodSignature.getParameterNames();
      long endTime = System.currentTimeMillis();
      baseLogMessage.setUri(urlStr);
      baseLogMessage.setType("异常日志");
      baseLogMessage.setServerIP(getRemoteIP(request));
      baseLogMessage.setMethod(request.getMethod());
      baseLogMessage.setAppName(systemPropetiesUtil.getSysName());
      baseLogMessage.setResult(message);
      baseLogMessage.setParameter(getParameter(method, joinPoint.getArgs()));
      baseLogMessage.setSpendTime((int) (endTime - startTime));
      baseLogMessage.setStartTime(endTime);
      LOGGER.info("{}", JsonUtils.objectToJson(baseLogMessage));
     // 数据库存储操作
    } catch (Exception e2) {
      e2.printStackTrace();
    }
 
  }
 
  /**
   * 根据方法和传入的参数获取请求参数
   */
  private Object getParameter(Method method, Object[] args) {
    List<Object> argList = new ArrayList<>();
    Parameter[] parameters = method.getParameters();
    for (int i = 0; i < parameters.length; i++) {
     
      RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
      if (requestBody != null) {
        argList.add(args[i]);
      }
      RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
      if (requestParam != null) {
        Map<String, Object> map = new HashMap<>();
        String key = parameters[i].getName();
        if (!StringUtils.isEmpty(requestParam.value())) {
          key = requestParam.value();
        }
        map.put(key, args[i]);
        argList.add(map);
      }
    }
    if (argList.size() == 0) {
      return null;
    } else if (argList.size() == 1) {
      return argList.get(0);
    } else {
      return argList;
    }
  }
 /**
   * 获取请求ip
   */
  public static String getRemoteIP(HttpServletRequest request) {
    String ip =null;
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("X-Forwarded-For");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
      ip = request.getRemoteAddr();
    }
    if (ip != null) {
      //对于通过多个代理的情况,最后IP为客户端真实IP,多个IP按照','分割
      int position = ip.indexOf(",");
      if (position > 0) {
        ip = ip.substring(0, position);
      }
    }
    return ip;
  }
}  

五、 问题

1、如果方法正常执行,不进入AOP类,请检查AOP的切点是否书写正确。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • SpringCloud 客户端Ribbon负载均衡的实现方法

    SpringCloud 客户端Ribbon负载均衡的实现方法

    Ribbon 是 Netflix 提供的一个基于 Http 和 TCP 的客户端负载均衡工具,且已集成在 Eureka 依赖中,这篇文章主要介绍了SpringCloud 客户端Ribbon负载均衡的实现方法,需要的朋友可以参考下
    2022-06-06
  • 浅谈Java slf4j日志简单理解

    浅谈Java slf4j日志简单理解

    这篇文章主要介绍了浅谈Java日志简单理解,详细的介绍了slf4j的概念和使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • Java编程Iterator迭代器设计原理及实现代码示例

    Java编程Iterator迭代器设计原理及实现代码示例

    这篇文章主要介绍了Java编程Iterator迭代器设计原理及实现代码示例,具有一定参考价值,需要的朋友可以了解下。
    2017-10-10
  • Springcloud Eureka配置及集群代码实例

    Springcloud Eureka配置及集群代码实例

    这篇文章主要介绍了Springcloud Eureka配置及集群代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-12-12
  • 几道常问Redis面试题,你能答对吗?

    几道常问Redis面试题,你能答对吗?

    在程序员面试过程中redis相关的知识是常被问到的话题。这篇文章主要介绍了13道Redis面试题,整理一下分享给大家,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 关于Mybatis动态sql中test的坑点总结

    关于Mybatis动态sql中test的坑点总结

    这篇文章主要介绍了关于Mybatis动态sql中test的坑点,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • 使用Java代码进行因数分解和求最小公倍数的示例

    使用Java代码进行因数分解和求最小公倍数的示例

    这篇文章主要介绍了使用Java代码进行因数分解和求最小公倍数的示例,都是基于最基础的算法原理实现,需要的朋友可以参考下
    2015-11-11
  • mybatis if test判断BigDecimal遇到的坑及解决

    mybatis if test判断BigDecimal遇到的坑及解决

    这篇文章主要介绍了mybatis if test判断BigDecimal遇到的坑及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Mybatis的特点及优点

    Mybatis的特点及优点

    Mybatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis。mybatis有哪些特点和优点呢?通过本文一起学习吧
    2016-12-12
  • mybatis实现一对一关联映射实例代码

    mybatis实现一对一关联映射实例代码

    这篇文章主要给大家介绍了关于mybatis实现一对一关联映射的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-11-11

最新评论