springBoot之如何獲取接口請(qǐng)求數(shù)據(jù)和返回?cái)?shù)據(jù)實(shí)現(xiàn)日志
一、獲取接口請(qǐng)求的數(shù)據(jù)
可以在Interceptor的afterCompletion中實(shí)現(xiàn)但是要重寫(xiě)RequestWrapper
代碼記錄如下:
HttpServletRequestFilter
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
?
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
?
import java.io.IOException;
?
@Component
@WebFilter(filterName = "HttpServletRequestFilter", urlPatterns = "/")
@Order(10000)
public class HttpServletRequestFilter implements Filter {
? ? @Override
? ? public void init(FilterConfig filterConfig) throws ServletException {
?
? ? }
?
? ? @Override
? ? public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
? ? ? ? ServletRequest requestWrapper = null;
? ? ? ? if(servletRequest instanceof HttpServletRequest) {
? ? ? ? ? ? requestWrapper = new RequestWrapper((HttpServletRequest) servletRequest);
? ? ? ? }
? ? ? ? //獲取請(qǐng)求中的流如何,將取出來(lái)的字符串,再次轉(zhuǎn)換成流,然后把它放入到新request對(duì)象中
? ? ? ? // 在chain.doFiler方法中傳遞新的request對(duì)象
? ? ? ? if(null == requestWrapper) {
? ? ? ? ? ? filterChain.doFilter(servletRequest, servletResponse);
? ? ? ? } else {
? ? ? ? ? ? filterChain.doFilter(requestWrapper, servletResponse);
? ? ? ? }
? ? }
?
? ? @Override
? ? public void destroy() {
?
? ? }
?
}RequestWrapper
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.*;?
?
public class RequestWrapper extends HttpServletRequestWrapper {
? ? private final String body;
?
? ? public RequestWrapper(HttpServletRequest request) {
? ? ? ? super(request);
? ? ? ? StringBuilder stringBuilder = new StringBuilder();
? ? ? ? BufferedReader bufferedReader = null;
? ? ? ? InputStream inputStream = null;
? ? ? ? try {
? ? ? ? ? ? inputStream = request.getInputStream();
? ? ? ? ? ? if (inputStream != null) {
? ? ? ? ? ? ? ? bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
? ? ? ? ? ? ? ? char[] charBuffer = new char[128];
? ? ? ? ? ? ? ? int bytesRead = -1;
? ? ? ? ? ? ? ? while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
? ? ? ? ? ? ? ? ? ? stringBuilder.append(charBuffer, 0, bytesRead);
? ? ? ? ? ? ? ? }
? ? ? ? ? ? } else {
? ? ? ? ? ? ? ? stringBuilder.append("");
? ? ? ? ? ? }
? ? ? ? } catch (IOException ex) {
?
? ? ? ? } finally {
? ? ? ? ? ? if (inputStream != null) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? inputStream.close();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? catch (IOException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (bufferedReader != null) {
? ? ? ? ? ? ? ? try {
? ? ? ? ? ? ? ? ? ? bufferedReader.close();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? catch (IOException e) {
? ? ? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? body = stringBuilder.toString();
? ? }
?
? ? @Override
? ? public ServletInputStream getInputStream() throws IOException {
? ? ? ? final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());
? ? ? ? ServletInputStream servletInputStream = new ServletInputStream() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean isFinished() {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public boolean isReady() {
? ? ? ? ? ? ? ? return false;
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public void setReadListener(ReadListener readListener) {
? ? ? ? ? ? }
? ? ? ? ? ? @Override
? ? ? ? ? ? public int read() throws IOException {
? ? ? ? ? ? ? ? return byteArrayInputStream.read();
? ? ? ? ? ? }
? ? ? ? };
? ? ? ? return servletInputStream;
?
? ? }
?
? ? @Override
? ? public BufferedReader getReader() throws IOException {
? ? ? ? return new BufferedReader(new InputStreamReader(this.getInputStream()));
? ? }
?
? ? public String getBody() {
? ? ? ? return this.body;
? ? }
?
}afterCompletion
? ? @Override
? ? public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exception)
? ? ? ? ? ? throws Exception {
?
? ? ? ? logger.debug("SessionInterceptor");
? ? ? ? // 獲取地址
? ? ? ? String url = request.getRequestURL().toString();
? ? ? ? String requestMethod = request.getMethod();
? ? ? ? String servletPath = request.getServletPath();
? ? ? ? String body = new RequestWrapper(request).getBody();
? ? ? ? String contentType = request.getContentType();
? ? ? ? Map reqMap = new HashMap();
? ? ? ? if(requestMethod.equals("POST")) {
? ? ? ? ? ? if(!contentType.equals("text/plain"))?
? ? ? ? ? ? ?? ?body = "body is file,don't show.";
? ? ? ? ? ? if(body.length()>1000)?
? ? ? ? ? ? ?? ?body = body.substring(0, 1000);
? ? ? ? }
? ? ? ? if(requestMethod.equals("GET")) {
? ? ? ? ? ? // 獲取請(qǐng)求參數(shù)
? ? ?? ??? ?Map ParameterMap = ?request.getParameterMap();
? ? ? ? ? ? Set<Map.Entry<String,String[]>> entry = ParameterMap.entrySet();
? ? ? ? ? ? Iterator<Map.Entry<String,String[]>> it = entry.iterator();
? ? ? ? ? ? while (it.hasNext()){
? ? ? ? ? ? ? ? Map.Entry<String,String[]> ?me = it.next();
? ? ? ? ? ? ? ? String key = me.getKey();
? ? ? ? ? ? ? ? String value = me.getValue()[0];
? ? ? ? ? ? ? ? reqMap.put(key,value);
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? logger.error("url: "+url+",requestMethod: "+requestMethod+",servletPath: "+servletPath+",body: " + body+",parameterMap: "+reqMap.toString());
? ? ? ??
? ? ? ??
? ? }二、獲取接口返回的數(shù)據(jù)
可以在filter中實(shí)現(xiàn)但是要重寫(xiě)ResponseWrapper,
代碼記錄如下:
HttpServletResponseFilter
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
?
import org.apache.log4j.Logger;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
?
import java.io.IOException;
?
@Component
@WebFilter(filterName = "HttpServletResponseFilter", urlPatterns = "/")
@Order(10000)
public class HttpServletResponseFilter implements Filter {
?? ?static Logger logger = Logger.getLogger(HttpServletResponseFilter.class.getName());
? ? @Override
? ? public void init(FilterConfig filterConfig) throws ServletException {
?
? ? }
?
? ? @Override
? ? public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
? ? ?? ?HttpServletRequest req = (HttpServletRequest) servletRequest;
? ? ? ? HttpServletResponse resp = (HttpServletResponse) servletResponse;
? ? ? ? ResponseWrapper mResp = new ResponseWrapper(resp); // 包裝響應(yīng)對(duì)象 resp 并緩存響應(yīng)數(shù)據(jù)
? ? ? ? filterChain.doFilter(req, mResp);
? ? ? ? byte[] bytes = mResp.getBytes(); // 獲取緩存的響應(yīng)數(shù)據(jù)
?? ? ? ?logger.error(new String(bytes,"utf-8"));
? ? }
?
? ? @Override
? ? public void destroy() {
?
? ? }
?
}ResponseWrapper
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;
?
public class ResponseWrapper extends HttpServletResponseWrapper {
?
? ? private ByteArrayOutputStream bytes = new ByteArrayOutputStream();
? ? private HttpServletResponse response;
? ? private PrintWriter pwrite;
?
? ? public ResponseWrapper(HttpServletResponse response) {
? ? ? ? super(response);
? ? ? ? this.response = response;
? ? }
?
? ? @Override
? ? public ServletOutputStream getOutputStream() throws IOException {
? ? ? ? return new MyServletOutputStream(bytes); // 將數(shù)據(jù)寫(xiě)到 byte 中
? ? }
?
? ? /**
? ? ?* 重寫(xiě)父類的 getWriter() 方法,將響應(yīng)數(shù)據(jù)緩存在 PrintWriter 中
? ? ?*/
? ? @Override
? ? public PrintWriter getWriter() throws IOException {
? ? ? ? try{
? ? ? ? ? ? pwrite = new PrintWriter(new OutputStreamWriter(bytes, "utf-8"));
? ? ? ? } catch(UnsupportedEncodingException e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }
? ? ? ? return pwrite;
? ? }
?
? ? /**
? ? ?* 獲取緩存在 PrintWriter 中的響應(yīng)數(shù)據(jù)
? ? ?* @return
? ? ?*/
? ? public byte[] getBytes() {
? ? ? ? if(null != pwrite) {
? ? ? ? ? ? pwrite.close();
? ? ? ? ? ? return bytes.toByteArray();
? ? ? ? }
?
? ? ? ? if(null != bytes) {
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? bytes.flush();
? ? ? ? ? ? } catch(IOException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? return bytes.toByteArray();
? ? }
?
? ? class MyServletOutputStream extends ServletOutputStream {
? ? ? ? private ByteArrayOutputStream ostream ;
?
? ? ? ? public MyServletOutputStream(ByteArrayOutputStream ostream) {
? ? ? ? ? ? this.ostream = ostream;
? ? ? ? }
?
? ? ? ? @Override
? ? ? ? public void write(int b) throws IOException {
? ? ? ? ? ? ostream.write(b); // 將數(shù)據(jù)寫(xiě)到 stream 中
? ? ? ? }
?
?? ??? ?@Override
?? ??? ?public boolean isReady() {
?? ??? ??? ?// TODO Auto-generated method stub
?? ??? ??? ?return false;
?? ??? ?}
?
?? ??? ?@Override
?? ??? ?public void setWriteListener(WriteListener listener) {
?? ??? ??? ?// TODO Auto-generated method stub
?? ??? ??? ?
?? ??? ?}
?
? ? }
?
}總結(jié)
本文參考了許多網(wǎng)上前輩們的踩坑歷程,在此就不列舉了,只做一記錄
希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java8深入學(xué)習(xí)系列(二)函數(shù)式編程
函數(shù)式編程,這個(gè)詞語(yǔ)由兩個(gè)名詞構(gòu)成,函數(shù),編程。編程這個(gè)詞我就不用解釋了,大家都是做這個(gè)的。函數(shù),其實(shí)單獨(dú)抽離出來(lái)這個(gè)詞語(yǔ),也并不陌生,那二者組合后的到底是什么呢,下面這篇文章主要給大家介紹了關(guān)于Java8函數(shù)式編程的相關(guān)資料,需要的朋友可以參考下。2017-08-08
使用Spring事物時(shí)不生效的場(chǎng)景及解決方法
今天介紹一下Spring事物不生效的場(chǎng)景,事物是我們?cè)陧?xiàng)目中經(jīng)常使用的,如果是Java的話,基本上都使用Spring的事物,不過(guò)Spring的事物如果使用不當(dāng),那么就會(huì)導(dǎo)致事物失效或者不回滾,最終導(dǎo)致數(shù)據(jù)不一致,下面我們意義列舉不生效的場(chǎng)景,并給出解決方法2023-09-09
舉例講解Java的RTTI運(yùn)行時(shí)類型識(shí)別機(jī)制
這篇文章主要介紹了Java的RTTI運(yùn)行時(shí)類型識(shí)別機(jī)制,包括泛化的Class引用以及類型檢查instanceof等知識(shí)點(diǎn),需要的朋友可以參考下2016-05-05
關(guān)于SpringMVC的數(shù)據(jù)綁定@InitBinder注解的使用
這篇文章主要介紹了關(guān)于SpringMVC的數(shù)據(jù)綁定@InitBinder注解的使用,在SpringMVC中,數(shù)據(jù)綁定的工作是由 DataBinder 類完成的,DataBinder可以將HTTP請(qǐng)求中的數(shù)據(jù)綁定到Java對(duì)象中,需要的朋友可以參考下2023-07-07
Java多線程實(shí)現(xiàn)TCP網(wǎng)絡(luò)Socket編程(C/S通信)
這篇文章主要介紹了Java多線程實(shí)現(xiàn)TCP網(wǎng)絡(luò)Socket編程(C/S通信),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10

