当前位置: 移动技术网 > IT编程>开发语言>Java > Springboot接口项目如何使用AOP记录日志

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

2020年06月13日  | 移动技术网IT编程  | 我要评论

一、 背景

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

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网