国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring Boot 記錄 Http 請求日志

SmallBoyO / 1350人閱讀

摘要:在使用開發(fā)的時候希望把,,等等的信息記錄到我們的日志中,方便我們排查問題,也能對系統(tǒng)的數(shù)據(jù)做一些統(tǒng)計。使用了來攔截并分發(fā)請求,我們只要自己實現(xiàn)一個并在其中對請求和響應做處理打印到日志中即可。

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

Spring 使用了 DispatcherServlet 來攔截并分發(fā)請求,我們只要自己實現(xiàn)一個 DispatcherServlet 并在其中對請求和響應做處理打印到日志中即可。

我們實現(xiàn)一個自己的分發(fā) Servlet ,它繼承于 DispatcherServlet,我們實現(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)建一個 json 對象,用來存放 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 getRequestHeaders(HttpServletRequest request) {
        Map headers = new HashMap<>();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            headers.put(headerName, request.getHeader(headerName));
        }
        return headers;

    }

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

LoggableDispatcherServlet 中,我們可以通過 HttpServletRequest 中的 InputStreamreader 來獲取請求的數(shù)據(jù),但如果我們直接在這里讀取了流或內(nèi)容,到后面的邏輯將無法進行下去,所以需要實現(xiàn)一個可以緩存的 HttpServletRequest。好在 Spring 提供這樣的類,就是 ContentCachingRequestWrapperContentCachingResponseWrapper, 根據(jù)官方的文檔這兩個類正好是來干這個事情的,我們只要將 HttpServletRequestHttpServletResponse 轉化即可。

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.

實現(xiàn)好我們的 LoggableDispatcherServlet后,接下來就是要指定使用 LoggableDispatcherServlet 來分發(fā)請求。

@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();
    }
}

增加一個簡單的 Controller 來測試一下

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

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

使用 curl 發(fā)送一個 Post 請求:

$ 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"
    }
}

當然打印出來是在一行中的,我進行了一下格式化。我們還可以在日志中增加請求的時間,耗費的時間以及異常信息等。

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73727.html

相關文章

  • Spring Boot 2.x(十一):AOP實戰(zhàn)--打印接口日志

    摘要:接口日志有啥用在我們?nèi)粘5拈_發(fā)過程中,我們可以通過接口日志去查看這個接口的一些詳細信息。在切入點返回內(nèi)容之后切入內(nèi)容可以用來對處理返回值做一些加工處理。 接口日志有啥用 在我們?nèi)粘5拈_發(fā)過程中,我們可以通過接口日志去查看這個接口的一些詳細信息。比如客戶端的IP,客戶端的類型,響應的時間,請求的類型,請求的接口方法等等,我們可以對這些數(shù)據(jù)進行統(tǒng)計分析,提取出我們想要的信息。 怎么拿到接口...

    Youngdze 評論0 收藏0
  • Spring-Boot學習筆記

    摘要:學習筆記使用很容易創(chuàng)建一個獨立運行運行內(nèi)嵌容器準生產(chǎn)級別的基于框架的項目,使用你可以不用或者只需要很少的配置。異常消息如果這個錯誤是由異常引起的。錯誤發(fā)生時請求的路徑。 Spring-Boot 1.5 學習筆記 使用Spring Boot很容易創(chuàng)建一個獨立運行(運行jar,內(nèi)嵌Servlet容器)、準生產(chǎn)級別的基于Spring框架的項目,使用Spring Boot你可以不用或者只需要很...

    curlyCheng 評論0 收藏0
  • Spring Boot應用監(jiān)控實戰(zhàn)

    摘要:概述之前講過容器的可視化監(jiān)控,即監(jiān)控容器的運行情況,包括使用率內(nèi)存占用網(wǎng)絡狀況以及磁盤空間等等一系列信息。實戰(zhàn)一下中添加依賴啟動應用程序之后,只要在瀏覽器中輸入端點信息就能獲得應用的一些狀態(tài)信息。 showImg(https://segmentfault.com/img/remote/1460000014684947); 概述 之前講過Docker容器的可視化監(jiān)控,即監(jiān)控容器的運行情...

    mtunique 評論0 收藏0
  • Spring Boot 2.0.2 參考指南(通用的應用程序屬性 ②)中文文檔

    摘要:通用的應用程序屬性代理主機代理端口嵌入式服務器配置屬性服務器應該綁定到的網(wǎng)絡地 通用的應用程序屬性 ② sendgrid(SendGridAutoConfiguration) spring.sendgrid.api-key= # SendGrid API key spring.sendgrid.proxy.host= # SendGrid 代理主機 spring.sendgrid.pr...

    WelliJhon 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<