欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot記錄Http請(qǐng)求日志的方法

 更新時(shí)間:2019年03月18日 14:53:28   作者:Simeone_xu  
這篇文章主要介紹了SpringBoot記錄Http請(qǐng)求日志的方法,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

在使用Spring Boot開(kāi)發(fā) web api 的時(shí)候希望把 request,request header ,response reponse header , uri, method 等等的信息記錄到我們的日志中,方便我們排查問(wèn)題,也能對(duì)系統(tǒng)的數(shù)據(jù)做一些統(tǒng)計(jì)。

Spring 使用了 DispatcherServlet 來(lái)攔截并分發(fā)請(qǐng)求,我們只要自己實(shí)現(xiàn)一個(gè) DispatcherServlet 并在其中對(duì)請(qǐng)求和響應(yīng)做處理打印到日志中即可。

我們實(shí)現(xiàn)一個(gè)自己的分發(fā) Servlet ,它繼承于 DispatcherServlet,我們實(shí)現(xiàn)自己的 doDispatch(HttpServletRequest request, HttpServletResponse response) 方法。

public class LoggableDispatcherServlet extends DispatcherServlet {

  private static final Logger logger = LoggerFactory.getLogger("HttpLogger");

  private static final ObjectMapper mapper = new ObjectMapper();

  @Override
  protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);
    ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);
    //創(chuàng)建一個(gè) json 對(duì)象,用來(lái)存放 http 日志信息
    ObjectNode rootNode = mapper.createObjectNode();
    rootNode.put("uri", requestWrapper.getRequestURI());
    rootNode.put("clientIp", requestWrapper.getRemoteAddr());
    rootNode.set("requestHeaders", mapper.valueToTree(getRequestHeaders(requestWrapper)));
    String method = requestWrapper.getMethod();
    rootNode.put("method", method);
    try {
      super.doDispatch(requestWrapper, responseWrapper);
    } finally {
      if(method.equals("GET")) {
        rootNode.set("request", mapper.valueToTree(requestWrapper.getParameterMap()));
      } else {
        JsonNode newNode = mapper.readTree(requestWrapper.getContentAsByteArray());
        rootNode.set("request", newNode);
      }

      rootNode.put("status", responseWrapper.getStatus());
      JsonNode newNode = mapper.readTree(responseWrapper.getContentAsByteArray());
      rootNode.set("response", newNode);

      responseWrapper.copyBodyToResponse();

      rootNode.set("responseHeaders", mapper.valueToTree(getResponsetHeaders(responseWrapper)));
      logger.info(rootNode.toString());
    }
  }

  private Map<String, Object> getRequestHeaders(HttpServletRequest request) {
    Map<String, Object> headers = new HashMap<>();
    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
      String headerName = headerNames.nextElement();
      headers.put(headerName, request.getHeader(headerName));
    }
    return headers;

  }

  private Map<String, Object> getResponsetHeaders(ContentCachingResponseWrapper response) {
    Map<String, Object> headers = new HashMap<>();
    Collection<String> headerNames = response.getHeaderNames();
    for (String headerName : headerNames) {
      headers.put(headerName, response.getHeader(headerName));
    }
    return headers;
  }

在 LoggableDispatcherServlet 中,我們可以通過(guò) HttpServletRequest 中的 InputStream 或 reader 來(lái)獲取請(qǐng)求的數(shù)據(jù),但如果我們直接在這里讀取了流或內(nèi)容,到后面的邏輯將無(wú)法進(jìn)行下去,所以需要實(shí)現(xiàn)一個(gè)可以緩存的 HttpServletRequest。好在 Spring 提供這樣的類(lèi),就是 ContentCachingRequestWrapper 和 ContentCachingResponseWrapper, 根據(jù)官方的文檔這兩個(gè)類(lèi)正好是來(lái)干這個(gè)事情的,我們只要將 HttpServletRequest 和 HttpServletResponse 轉(zhuǎn)化即可。

HttpServletRequest wrapper that caches all content read from the input stream and reader, and allows this content to be retrieved via a byte array.
Used e.g. by AbstractRequestLoggingFilter. Note: As of Spring Framework 5.0, this wrapper is built on the Servlet 3.1 API.

HttpServletResponse wrapper that caches all content written to the output stream and writer, and allows this content to be retrieved via a byte array.
Used e.g. by ShallowEtagHeaderFilter. Note: As of Spring Framework 5.0, this wrapper is built on the Servlet 3.1 API.

實(shí)現(xiàn)好我們的 LoggableDispatcherServlet后,接下來(lái)就是要指定使用 LoggableDispatcherServlet 來(lái)分發(fā)請(qǐng)求。

@SpringBootApplication
public class SbDemoApplication implements ApplicationRunner {

  public static void main(String[] args) {
    SpringApplication.run(SbDemoApplication.class, args);
  }
  @Bean
  public ServletRegistrationBean dispatcherRegistration() {
    return new ServletRegistrationBean(dispatcherServlet());
  }
  @Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
  public DispatcherServlet dispatcherServlet() {
    return new LoggableDispatcherServlet();
  }
}

增加一個(gè)簡(jiǎn)單的 Controller 來(lái)測(cè)試一下

@RestController
@RequestMapping("/hello")
public class HelloController {

  @RequestMapping(value = "/word", method = RequestMethod.POST)
  public Object hello(@RequestBody Object object) {
    return object;
  }
}

使用 curl 發(fā)送一個(gè) Post 請(qǐng)求:

$ curl --header "Content-Type: application/json" \
 --request POST \
 --data '{"username":"xyz","password":"xyz"}' \
 http://localhost:8080/hello/word
{"username":"xyz","password":"xyz"}

查看打印的日志:

{
  "uri":"/hello/word",
  "clientIp":"0:0:0:0:0:0:0:1",
  "requestHeaders":{
    "content-length":"35",
    "host":"localhost:8080",
    "content-type":"application/json",
    "user-agent":"curl/7.54.0",
    "accept":"*/*"
  },
  "method":"POST",
  "request":{
    "username":"xyz",
    "password":"xyz"
  },
  "status":200,
  "response":{
    "username":"xyz",
    "password":"xyz"
  },
  "responseHeaders":{
    "Content-Length":"35",
    "Date":"Sun, 17 Mar 2019 08:56:50 GMT",
    "Content-Type":"application/json;charset=UTF-8"
  }
}

當(dāng)然打印出來(lái)是在一行中的,我進(jìn)行了一下格式化。我們還可以在日志中增加請(qǐng)求的時(shí)間,耗費(fèi)的時(shí)間以及異常信息等。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java8新特性之新日期時(shí)間庫(kù)的使用教程

    Java8新特性之新日期時(shí)間庫(kù)的使用教程

    這篇文章主要給大家介紹了關(guān)于Java8新特性之新日期時(shí)間庫(kù)使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • java線(xiàn)程中斷?interrupt?和?LockSupport解析

    java線(xiàn)程中斷?interrupt?和?LockSupport解析

    這篇文章主要為大家介紹了java線(xiàn)程中斷?interrupt?和?LockSupport示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • spring無(wú)法引入注解及import org.springframework.web.bind.annotation.*報(bào)錯(cuò)的解決

    spring無(wú)法引入注解及import org.springframework.web.bind.annota

    本文主要介紹了spring無(wú)法引入注解及import org.springframework.web.bind.annotation.*報(bào)錯(cuò)的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Java網(wǎng)絡(luò)編程之IO模型阻塞與非阻塞簡(jiǎn)要分析

    Java網(wǎng)絡(luò)編程之IO模型阻塞與非阻塞簡(jiǎn)要分析

    這篇文章主要介紹Java網(wǎng)絡(luò)編程中的IO模型阻塞與非阻塞簡(jiǎn)要分析,文中附有示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-09-09
  • Spring Cloud Netflix架構(gòu)淺析(小結(jié))

    Spring Cloud Netflix架構(gòu)淺析(小結(jié))

    這篇文章主要介紹了Spring Cloud Netflix架構(gòu)淺析(小結(jié)),詳解的介紹了Spring Cloud Netflix的概念和組件等,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • java結(jié)合WebSphere MQ實(shí)現(xiàn)接收隊(duì)列文件功能

    java結(jié)合WebSphere MQ實(shí)現(xiàn)接收隊(duì)列文件功能

    WebSphereMQ,也稱(chēng)MQSeries,以一致的、可靠的和易于管理的方式來(lái)連接應(yīng)用程序,并為跨部門(mén)、企業(yè)范圍的集成提供了可靠的基礎(chǔ)。通過(guò)為重要的消息和事務(wù)提供可靠的、一次且僅一次的傳遞,MQ可以處理復(fù)雜的通信協(xié)議,并動(dòng)態(tài)地將消息傳遞工作負(fù)載分配給可用的資源。
    2015-10-10
  • iOS獲取AppIcon and LaunchImage''s name(app圖標(biāo)和啟動(dòng)圖片名字)

    iOS獲取AppIcon and LaunchImage''s name(app圖標(biāo)和啟動(dòng)圖片名字)

    這篇文章主要介紹了iOS獲取AppIcon and LaunchImage's name(app圖標(biāo)和啟動(dòng)圖片名字)的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-08-08
  • java double類(lèi)型相加精度問(wèn)題的解決

    java double類(lèi)型相加精度問(wèn)題的解決

    這篇文章主要介紹了java double類(lèi)型相加精度問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • 利用Postman和Chrome的開(kāi)發(fā)者功能探究項(xiàng)目(畢業(yè)設(shè)計(jì)項(xiàng)目)

    利用Postman和Chrome的開(kāi)發(fā)者功能探究項(xiàng)目(畢業(yè)設(shè)計(jì)項(xiàng)目)

    這篇文章主要介紹了利用Postman和Chrome的開(kāi)發(fā)者功能探究項(xiàng)目(畢業(yè)設(shè)計(jì)項(xiàng)目),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Java匿名類(lèi),匿名內(nèi)部類(lèi)實(shí)例分析

    Java匿名類(lèi),匿名內(nèi)部類(lèi)實(shí)例分析

    這篇文章主要介紹了Java匿名類(lèi),匿名內(nèi)部類(lèi),結(jié)合實(shí)例形式分析了Java匿名類(lèi),匿名內(nèi)部類(lèi)相關(guān)原理、用法及操作注意事項(xiàng),需要的朋友可以參考下
    2020-04-04

最新評(píng)論