日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解在Spring MVC或Spring Boot中使用Filter打印請求參數問題

瀏覽:72日期:2023-05-19 16:33:06

使用Spring MVC或Spring Boot中打印或記錄日志一般使用AOP記錄Request請求和Response響應參數,在不使用AOP的前提下,如果在Filter中打印日志,在打印或消費請求類型為Content-Type:application/json的請求時,會出現嚴重的問題。

在Spring體系中,過濾器的定義我們一般采用繼承OncePerRequestFilter的方式,當然也可以使用原始的Filter。

錯誤寫法一:

如果不對request和response進行處理,使用偽代碼采用如下寫法打印請求和響應參數(注:此時request請求類型為Post,接收的是Json數據)

@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponseresponse, FilterChain filterChain) throws ServletException, IOException { filterChain.doFilter(request, response); printRequestLog(request); printResonseLog(response); }

運行測試后你會發現拋出如下異常:

java.io.IOException: Stream closed at org.apache.catalina.connector.InputBuffer.read(InputBuffer.java:359) ~[tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.connector.CoyoteInputStream.read(CoyoteInputStream.java:132) ~[tomcat-embed-core-9.0.31.jar:9.0.31] at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284) ~[na:1.8.0_191] at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326) ~[na:1.8.0_191] at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178) ~[na:1.8.0_191] at java.io.InputStreamReader.read(InputStreamReader.java:184) ~[na:1.8.0_191] at java.io.BufferedReader.fill(BufferedReader.java:161) ~[na:1.8.0_191] at java.io.BufferedReader.readLine(BufferedReader.java:324) ~[na:1.8.0_191] at java.io.BufferedReader.readLine(BufferedReader.java:389) ~[na:1.8.0_191] at com.micro.backend.filter.LoggingFilter.getBodyString(LoggingFilter.java:60) [classes/:na] at com.micro.backend.filter.LoggingFilter.doFilterInternal(LoggingFilter.java:49) [classes/:na] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:94) [spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.1.14.RELEASE.jar:5.1.14.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1639) [tomcat-embed-core-9.0.31.jar:9.0.31] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.31.jar:9.0.31] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_191] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_191] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.31.jar:9.0.31] at java.lang.Thread.run(Thread.java:748) [na:1.8.0_191]

錯誤寫法二:

如果不對request和response進行處理,使用偽代碼采用如下寫法打印請求和響應參數(注:此時request請求類型為Post,接收的是Json數據)

@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponseresponse, FilterChain filterChain) throws ServletException, IOException { printRequestLog(request); printResonseLog(response); filterChain.doFilter(request, response); }

運行測試后你會發現拋出如下異常:

org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing

遇到這樣的問題你是不是有坐立不安、心煩意亂、百爪撓心的痛楚,不要著急,下面我給出一個解決方案。

首先我們使用裝飾器模式,創建request和response兩個包裝類,如下:

import javax.servlet.ReadListener;import javax.servlet.ServletInputStream;import javax.servlet.ServletRequest;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import java.io.*;import java.nio.charset.Charset;/*** @Description: 請求包裝器* @Author: liuliya* @CreateDate: 2020/4/29 10:00*/public class RequestWrapper extends HttpServletRequestWrapper { private final byte[] body; public RequestWrapper(HttpServletRequest request) throws IOException { super(request); body = getRequestBodyString(request).getBytes(Charset.defaultCharset()); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream bais = new ByteArrayInputStream(body); return new ServletInputStream() { @Override public int read() throws IOException {return bais.read(); } @Override public boolean isFinished() {return false; } @Override public boolean isReady() {return false; } @Override public void setReadListener(ReadListener listener) { } }; } public String getRequestBodyString(ServletRequest request) { StringBuilder sb = new StringBuilder(); InputStream inputStream = null; BufferedReader reader = null; try { inputStream = request.getInputStream(); reader = new BufferedReader(new InputStreamReader(inputStream, Charset.defaultCharset())); String line; while ((line = reader.readLine()) != null) {sb.append(line); } } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) {try { inputStream.close();} catch (IOException e) { e.printStackTrace();} } if (reader != null) {try { reader.close();} catch (IOException e) { e.printStackTrace();} } } return sb.toString(); }}

package com.micro.backend.filter.support; import org.apache.commons.io.output.TeeOutputStream; import javax.servlet.ServletOutputStream;import javax.servlet.ServletResponse;import javax.servlet.WriteListener;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpServletResponseWrapper;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.PrintWriter; /** * @Description: 響應包裝器 * @Author: liuliya * @CreateDate: 2020/4/29 10:00 */public class ResponseWrapper extends HttpServletResponseWrapper { private final ByteArrayOutputStream bos = new ByteArrayOutputStream(); private PrintWriter writer = new PrintWriter(bos); public ResponseWrapper(HttpServletResponse response) { super(response); } @Override public ServletResponse getResponse() { return this; } @Override public ServletOutputStream getOutputStream() throws IOException { return new ServletOutputStream() { @Override public boolean isReady() {return false; } @Override public void setWriteListener(WriteListener listener) { } private TeeOutputStream tee = new TeeOutputStream(ResponseWrapper.super.getOutputStream(), bos); @Override public void write(int b) throws IOException {tee.write(b); } }; } @Override public PrintWriter getWriter() throws IOException { return new TeePrintWriter(super.getWriter(), writer); } public byte[] toByteArray() { return bos.toByteArray(); }}

package com.micro.backend.filter.support;import java.io.PrintWriter;//PrintWriter是一種寫入字符的一種操作類,可以寫入字符,TeePrintWriter繼承了他,主要功能是把原始的字符流copy到branch里面。public class TeePrintWriter extends PrintWriter { PrintWriter branch; public TeePrintWriter(PrintWriter main, PrintWriter branch) { super(main, true); this.branch = branch; } public void write(char buf[], int off, int len) { super.write(buf, off, len); super.flush(); branch.write(buf, off, len); branch.flush(); } public void write(String s, int off, int len) { super.write(s, off, len); super.flush(); branch.write(s, off, len); branch.flush(); } public void write(int c) { super.write(c); super.flush(); branch.write(c); branch.flush(); } public void flush() { super.flush(); branch.flush(); }}

接下來創建最重要的LoggingFilter類,繼承OncePerRequestFilter,或者直接繼承Servlet中原始的Filter。

package com.micro.backend.filter; import com.micro.backend.filter.support.RequestWrapper;import com.micro.backend.filter.support.ResponseWrapper;import lombok.extern.slf4j.Slf4j;import org.springframework.context.annotation.Configuration;import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.IOException;import java.io.UnsupportedEncodingException; /*** @Author: liuliya* @CreateDate: 2020/4/28 23:30*/@Slf4j@Configurationpublic class LoggingFilter extends OncePerRequestFilter { private static final String REQUEST_PREFIX_NAME = 'Request請求: '; private static final String RESPONSE_PREFIX_NAME = 'Response請求: '; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { request = new RequestWrapper(request); response = new ResponseWrapper(response); filterChain.doFilter(request, response); printRequestLog(request); printResponseLog((ResponseWrapper) response); } private void printRequestLog(final HttpServletRequest request) { StringBuilder msg = new StringBuilder(); msg.append(REQUEST_PREFIX_NAME); HttpSession session = request.getSession(false); if (session != null) { msg.append('sessionId = ').append(session.getId()).append('; '); } if (request.getMethod() != null) { msg.append('method = ').append(request.getMethod()).append('; '); } if (request.getContentType() != null) { msg.append('contentType = ').append(request.getContentType()).append('; '); } msg.append('uri = ').append(request.getRequestURI()); if (request.getQueryString() != null) { msg.append(’?’).append(request.getQueryString()); } if (request instanceof RequestWrapper && !isMultipart(request) && !isBinaryContent(request)) { RequestWrapper requestWrapper = (RequestWrapper) request; msg.append('; payload = ').append(requestWrapper.getRequestBodyString(request)); } log.info(msg.toString()); } private boolean isBinaryContent(final HttpServletRequest request) { if (request.getContentType() == null) { return false; } return request.getContentType().startsWith('image')|| request.getContentType().startsWith('video')|| request.getContentType().startsWith('audio'); } private boolean isMultipart(final HttpServletRequest request) { return request.getContentType() != null&& request.getContentType().startsWith('multipart/form-data'); } private void printResponseLog(final ResponseWrapper response) { StringBuilder msg = new StringBuilder(); msg.append(RESPONSE_PREFIX_NAME); try { msg.append('; payload = ') .append(new String(response.toByteArray(), response.getCharacterEncoding())); } catch (UnsupportedEncodingException e) { log.warn('Failed to parse response payload', e); } log.info(msg.toString()); } }

參考以上我整理出的代碼,你就會發現奇跡!!!

為什么要這么寫呢,其本質是把請求流拷貝了一份,一個供filterChain向下傳遞,一個來做流的消費,再有一個就是運用裝飾器模式的精髓所在。

到此這篇關于詳解在Spring MVC或Spring Boot中使用Filter打印請求參數問題的文章就介紹到這了,更多相關SpringBoot Filter打印請求參數內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产日韩专区| 日韩激情视频网站| 精品国产亚洲一区二区三区大结局| 日本欧美在线看| 中文视频一区| 亚洲2区在线| 亚洲欧美日韩专区| 伊人久久亚洲| 欧美天堂在线| 乱一区二区av| 狠狠久久伊人中文字幕| 久久久久九九精品影院| 国产精品玖玖玖在线资源| 免费在线观看一区| 成人一区不卡| 精品少妇一区| 欧洲av不卡| 蜜桃成人av| 麻豆91精品| 日韩高清不卡在线| 国产高清视频一区二区| 精品一区二区三区免费看| 久久精品国产网站| 国产欧美一区二区三区精品酒店| 欧美日韩一二三四| 国产精品美女久久久浪潮软件| 日av在线不卡| 国产九九精品| 亚洲爱爱视频| 亚洲欧美日本国产专区一区| 亚洲精品一级二级三级| 日韩av一二三| 麻豆精品新av中文字幕| 亚洲午夜天堂| 尹人成人综合网| 亚洲精品第一| 日韩亚洲精品在线观看| 麻豆精品国产91久久久久久| 韩国久久久久久| 黄色亚洲大片免费在线观看| 亚洲精品看片| 精品淫伦v久久水蜜桃| 亚洲成a人片| 男女男精品网站| 国产精品xvideos88| 日韩成人高清| 免费欧美在线视频| 免费视频一区二区三区在线观看| 成人免费网站www网站高清| 首页欧美精品中文字幕| 国产精品久久久久久久久久齐齐| 精品亚洲a∨一区二区三区18| 久久国产日韩| 亚洲一区二区网站| 欧美黄页在线免费观看| 国产99久久久国产精品成人免费| 亚洲精品九九| 日本久久精品| 久久先锋影音| 久久男人av| 日韩视频二区| 美女免费视频一区| 亚洲综合另类| 国产欧美日韩一区二区三区四区| 一区二区三区四区日本视频| 亚洲专区一区| 国产精品毛片aⅴ一区二区三区| 欧美日韩在线网站| 国产欧美一区二区三区国产幕精品 | 首页亚洲欧美制服丝腿| 久久影视三级福利片| 乱人伦精品视频在线观看| 国产精品伦理久久久久久| 日韩影院精彩在线| 国产一区二区三区不卡av| 日韩一区精品视频| 成人看片网站| 美女久久99| 日韩精品欧美精品| 国产在线成人| 国产成人精品一区二区三区免费| 日韩精品一区第一页| 中文字幕成在线观看| 国产欧美自拍| 亚洲理论在线| 日韩精品欧美激情一区二区| 国产日韩一区二区三免费高清| 99国产精品99久久久久久粉嫩| 精品国产一区二区三区噜噜噜| 亚洲一区网站| 久久uomeier| 国产精品一二| 亚洲人亚洲人色久| 99热精品在线| 久久久久99| 精品国产亚洲一区二区三区在线| 亚洲精品看片| 亚洲在线电影| 亚洲二区视频| 精品国产网站| 久久国产日韩欧美精品| 中文字幕一区二区三区在线视频| 欧美亚洲国产激情| 国产精品福利在线观看播放| 国产精品日韩精品中文字幕| 成人av二区| 日韩欧美一区二区三区免费看| 国产精品99久久免费| 亚洲精品乱码久久久久久蜜桃麻豆| 久久影视一区| 亚洲三级欧美| av资源亚洲| 国产不卡精品| 精品久久一区| 蜜桃91丨九色丨蝌蚪91桃色| 欧美aa在线视频| 日韩激情一二三区| 日产精品一区二区| 91超碰国产精品| 国产精品白丝一区二区三区| 午夜精品福利影院| 亚洲一区免费| 日本视频一区二区| 国产suv精品一区| 欧美日韩a区| 综合一区二区三区| 免费国产自线拍一欧美视频| 欧美va天堂在线| 久久激情中文| 久久精品影视| 99久久99久久精品国产片果冰| 欧美日韩国产观看视频| 91综合网人人| 色在线视频观看| 久久精品二区三区| 国产一区二区精品| 六月天综合网| 亚洲精品精选| 日本精品另类| 国产日韩欧美一区二区三区| 欧美中文高清| 国产精品99久久久久久董美香| 国产精品18| 欧美激情精品| 精品国产亚洲日本| 中文字幕在线免费观看视频| 日韩av福利| 国精品一区二区三区| 欧美日韩国产精品一区二区亚洲| 欧美特黄一级大片| 日韩欧美一区二区三区免费观看| 日韩不卡免费高清视频| 欧美日韩国产免费观看视频| 免费精品视频| 亚洲精品护士| 麻豆精品视频在线观看免费| 国产一区二区三区黄网站| 日韩精品永久网址| 亚洲国产专区校园欧美| 国产婷婷精品| 色8久久久久| 久久av综合| 99热国内精品| 亚洲欧洲美洲国产香蕉| 美腿丝袜亚洲三区| 综合日韩av| 在线 亚洲欧美在线综合一区| 在线观看视频免费一区二区三区| 日韩国产一区二| 91视频一区| 国产婷婷精品| 国产精品日本一区二区不卡视频| 首页国产精品| 黄色精品网站| 国产亚洲欧美日韩精品一区二区三区| 久久免费精品| 国产在线不卡| 日本不卡视频在线| 给我免费播放日韩视频| 合欧美一区二区三区| 亚洲tv在线| 91偷拍一区二区三区精品| av成人国产| 欧美国产不卡| 午夜一区在线| 麻豆国产精品777777在线| 免费不卡中文字幕在线| 97精品资源在线观看| 伊伊综合在线| 日韩精品1区2区3区| 日韩电影二区| 日韩一区二区三区高清在线观看| 国产欧洲在线| 日韩有吗在线观看| 香蕉视频亚洲一级| 亚洲tv在线| 亚洲国产专区校园欧美| 久久精品99国产精品| 国产专区一区| 国产乱码精品一区二区亚洲|