其他
SpringBoot正确打日志的姿势
前篇
本文简介
前篇侧重 Log4j2 的配置,本篇侧重统一日志处理的应用,以下包含 HTTP 请求的日志处理、Exception 异常日志处理。
HTTP 请求日志
1、明确日志记录的内容
示例:用户、IP地址、Method、URI、请求参数、请求体
2、全局拦截 MDCFilter.java
1package com.anoyi.config.server;
2
3import lombok.extern.log4j.Log4j2;
4import org.slf4j.MDC;
5import org.springframework.http.HttpMethod;
6import org.springframework.stereotype.Component;
7import org.springframework.web.filter.OncePerRequestFilter;
8
9import javax.servlet.FilterChain;
10import javax.servlet.ReadListener;
11import javax.servlet.ServletException;
12import javax.servlet.ServletInputStream;
13import javax.servlet.http.HttpServletRequest;
14import javax.servlet.http.HttpServletRequestWrapper;
15import javax.servlet.http.HttpServletResponse;
16import java.io.*;
17
18/**
19 * 拦截请求信息,添加到日志
20 */
21
22 4j2
23public class MDCFilter extends OncePerRequestFilter {
24
25
26 protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
27 try {
28 MDC.put("user", request.getRemoteUser());
29 String query = request.getQueryString() != null ? "?" + request.getQueryString() : "";
30 if (request.getMethod().equals(HttpMethod.POST.name())) {
31 MultiReadHttpServletRequest multiReadHttpServletRequest = new MultiReadHttpServletRequest(request);
32 log.info("IP:{}, Method:{}, URI:{} Body:{}", request.getRemoteAddr(), request.getMethod(), request.getRequestURI() + query, multiReadHttpServletRequest.getRequestBody());
33 chain.doFilter(multiReadHttpServletRequest, response);
34 } else {
35 log.info("IP:{}, Method:{}, URI:{}", request.getRemoteAddr(), request.getMethod(), request.getRequestURI() + query);
36 chain.doFilter(request, response);
37 }
38 } finally {
39 MDC.clear();
40 }
41 }
42
43 /**
44 * HttpServletRequest 请求体多读
45 */
46 class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
47
48 // 缓存 RequestBody
49 private String requestBody;
50
51 MultiReadHttpServletRequest(HttpServletRequest request) {
52 super(request);
53 requestBody = "";
54 try {
55 StringBuilder stringBuilder = new StringBuilder();
56 InputStream inputStream = request.getInputStream();
57 byte[] bs = new byte[1024];
58 int len;
59 while ((len = inputStream.read(bs)) != -1) {
60 stringBuilder.append(new String(bs, 0, len));
61 }
62 requestBody = stringBuilder.toString();
63 } catch (IOException e) {
64 e.printStackTrace();
65 }
66 }
67
68
69 public ServletInputStream getInputStream() throws IOException {
70 final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(requestBody.getBytes());
71
72 return new ServletInputStream() {
73 public int read() throws IOException {
74 return byteArrayInputStream.read();
75 }
76
77
78 public boolean isFinished() {
79 return byteArrayInputStream.available() == 0;
80 }
81
82
83 public boolean isReady() {
84 return true;
85 }
86
87
88 public void setReadListener(ReadListener readListener) {
89
90 }
91 };
92 }
93
94
95 public BufferedReader getReader() throws IOException {
96 return new BufferedReader(new InputStreamReader(this.getInputStream()));
97 }
98
99 String getRequestBody() {
100 return requestBody.replaceAll("\n", "");
101 }
102 }
103
104}
3、配置日志 Pattern
1logging:
2 pattern:
3 console: "%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%15.15t] %-40.40c{1.} [%X{user}] : %m%n%xwEx"
说明:
MDC.put("user", request.getRemoteUser());
=>%X{user}
© 著作权归作者所有,转载或内容合作请联系作者
● Spring Boot 定制 parent 快速构建应用
● Spring Boot 日志处理你还在用Logback?
如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!