gpt4 book ai didi

SpringBoot记录Http请求日志的方法

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 28 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章SpringBoot记录Http请求日志的方法由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

在使用spring boot开发 web api 的时候希望把 request,request header ,response reponse header , uri, method 等等的信息记录到我们的日志中,方便我们排查问题,也能对系统的数据做一些统计.

spring 使用了 dispatcherservlet 来拦截并分发请求,我们只要自己实现一个 dispatcherservlet 并在其中对请求和响应做处理打印到日志中即可.

我们实现一个自己的分发 servlet ,它继承于 dispatcherservlet,我们实现自己的 dodispatch(httpservletrequest request, httpservletresponse response) 方法.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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);
     //创建一个 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<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 中,我们可以通过 httpservletrequest 中的 inputstream 或 reader 来获取请求的数据,但如果我们直接在这里读取了流或内容,到后面的逻辑将无法进行下去,所以需要实现一个可以缓存的 httpservletrequest。好在 spring 提供这样的类,就是 contentcachingrequestwrapper 和 contentcachingresponsewrapper, 根据官方的文档这两个类正好是来干这个事情的,我们只要将 httpservletrequest 和 httpservletresponse 转化即可.

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. 。

实现好我们的 loggabledispatcherservlet后,接下来就是要指定使用 loggabledispatcherservlet 来分发请求.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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 来测试一下 。

?
1
2
3
4
5
6
7
8
9
@restcontroller
@requestmapping ( "/hello" )
public class hellocontroller {
 
   @requestmapping (value = "/word" , method = requestmethod.post)
   public object hello( @requestbody object object) {
     return object;
   }
}

使用 curl 发送一个 post 请求:

?
1
2
3
4
5
$ curl --header "content-type: application/json" \
  --request post \
  --data '{"username":"xyz","password":"xyz"}' \
  http: //localhost:8080/hello/word
{ "username" : "xyz" , "password" : "xyz" }

查看打印的日志:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
   "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"
   }
}

当然打印出来是在一行中的,我进行了一下格式化。我们还可以在日志中增加请求的时间,耗费的时间以及异常信息等.

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

原文链接:https://segmentfault.com/a/1190000018535456 。

最后此篇关于SpringBoot记录Http请求日志的方法的文章就讲到这里了,如果你想了解更多关于SpringBoot记录Http请求日志的方法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com