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

详解AOP与Filter拦截请求打印日志实用例子

程序员文章站 2024-02-24 19:55:16
相信各位同道在写代码的时候,肯定会写一些日志打印,因为这对往后的运维而言,至关重要的。 那么我们请求一个restfull接口的时候,哪些信息是应该被日志记录的呢? 以下...

相信各位同道在写代码的时候,肯定会写一些日志打印,因为这对往后的运维而言,至关重要的。

那么我们请求一个restfull接口的时候,哪些信息是应该被日志记录的呢?

以下做了一个基本的简单例子,这里只是示例说明基本常规实现记录的信息,根据项目的真实情况选用:

1 . http请求拦截器(filter) : 从httpservletrequest获取基本的请求信息

import name.ealen.util.httputil;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.beans.factory.annotation.qualifier;
import org.springframework.boot.web.servlet.filterregistrationbean;
import org.springframework.context.annotation.bean;
import org.springframework.context.annotation.configuration;
import org.springframework.core.annotation.order;

import javax.servlet.*;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;
import java.io.ioexception;

/**
 * created by ealenxie on 2018/9/7 15:56.
 * http请求拦截器,日志打印请求基本相关信息
 */
@configuration
public class filterconfiguration {

  private static final logger log = loggerfactory.getlogger(filterconfig.class);

  @bean
  @order(integer.min_value)
  @qualifier("filterregistration")
  public filterregistrationbean filterregistration() {
    filterregistrationbean<filter> registration = new filterregistrationbean<>();
    registration.setfilter(controllerfilter());
    registration.addurlpatterns("/*");
    return registration;
  }

  private filter controllerfilter() {
    return new filter() {
      @override
      public void init(filterconfig filterconfig) {
        log.info("controllerfilter init success");
      }

      @override
      public void dofilter(servletrequest servletrequest, servletresponse servletresponse, filterchain chain) throws ioexception, servletexception {
        httpservletrequest request = (httpservletrequest) servletrequest;
        httpservletresponse response = (httpservletresponse) servletresponse;
        string requestid = request.getheader("request-id");
        if (requestid == null) requestid = request.getrequestedsessionid();
        system.out.println();
        log.info("http request request-id : " + requestid);
        log.info("http request information : {\"uri\":\"" + request.getrequesturl() +
            "\",\"requestmethod\":\"" + request.getmethod() +
            "\",\"clientip\":\"" + httputil.getipaddress(request) +
            "\",\"content-type\":\"" + request.getcontenttype() +
            "\"}");
        chain.dofilter(request, response);
      }

      @override
      public void destroy() {
        log.info("controllerfilter destroy");
      }
    };
  }
}

2 . controller的拦截aop : 获取 请求的对象,请求参数,返回数据,请求返回状态,内部方法耗时。

import com.alibaba.fastjson.json;
import org.aspectj.lang.proceedingjoinpoint;
import org.aspectj.lang.annotation.around;
import org.aspectj.lang.annotation.aspect;
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.core.env.environment;
import org.springframework.http.httpstatus;
import org.springframework.http.responseentity;
import org.springframework.stereotype.component;

import javax.annotation.resource;

/**
 * created by ealenxie on 2018/9/7 14:19.
 * aop打印日志 : 请求的对象,请求参数,返回数据,请求状态,内部方法耗时
 */
@aspect
@component
public class controllerinterceptor {

  private static final logger log = loggerfactory.getlogger(controllerinterceptor.class);
  @resource
  private environment environment;

  @around(value = "execution (* name.ealen.web.*.*(..))")
  public object processapifacade(proceedingjoinpoint pjp) {
    string appname;
    try {
      appname = environment.getproperty("spring.application.name").touppercase();
    } catch (exception e) {
      appname = "unnamed";
    }
    long starttime = system.currenttimemillis();
    string name = pjp.gettarget().getclass().getsimplename();
    string method = pjp.getsignature().getname();
    object result = null;
    httpstatus status = null;
    try {
      result = pjp.proceed();
      log.info("requesttarget : " + appname + "." + name + "." + method);
      log.info("requestparam : " + json.tojson(pjp.getargs()));
      if (result instanceof responseentity) {
        status = ((responseentity) result).getstatuscode();
      } else {
        status = httpstatus.ok;
      }
    } catch (throwable throwable) {
      status = httpstatus.internal_server_error;
      result = new responseentity<>("{\"internal server error\" : \"" + throwable.getmessage() + "\"}", status);
      throwable.printstacktrace();
    } finally {
      log.info("responseentity : {" + "\"httpstatus\":\"" + status.tostring() + "\"" + ",\"responsebody\": " + json.tojson(result) + "}");
      log.info("internal method cost time: {}ms", system.currenttimemillis() - starttime);
    }
    return result;
  }
}

3 . 提供一个简单的restfull接口 :

package name.ealen.web;

import org.springframework.http.httpstatus;
import org.springframework.http.responseentity;
import org.springframework.web.bind.annotation.requestbody;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.restcontroller;

/**
 * created by ealenxie on 2018/9/7 14:24.
 */
@restcontroller
public class sayhellocontroller {

  @requestmapping("/sayhello")
  public string sayhello() {
    return "hello world";
  }

  @requestmapping("/say")
  public responseentity<?> say(@requestbody object o) {
    return new responseentity<>(o, httpstatus.ok);
  }

}

4 . 使用postman进行基本测试 :

详解AOP与Filter拦截请求打印日志实用例子

5 . 控制台可以看到基本效果 :

详解AOP与Filter拦截请求打印日志实用例子

以上只是关于controller应该记录日志的一个简单的例子,完整代码可见 https://github.com/ealenxie/springboot-controller-logger

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