欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-07-06 18:01:36
一、 背景一直想给项目构建一个统一的日志收集系统,先迈出第一步,构建一个日志收集类,用aop实现无侵入日志收集二、 环境1.此随笔内容基于spring boot项目2.数据库为mysql 5.7.9版...

一、 背景

一直想给项目构建一个统一的日志收集系统,先迈出第一步,构建一个日志收集类,用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的切点是否书写正确。

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