我希望在spring中寫一個除錯用的aop,能夠列印http請求和回應的明文
就是能列印這樣的請求明文
POST /echo HTTP/1.1
Host: localhost
Content-Type: text/plain;charset=UTF-8
{"abc":"xyz"}
列印這樣的請求回應
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Date: Mon, 08 Mar 2021 09:57:23 GMT
{"abc":"xyz"}
uj5u.com熱心網友回復:
你可以搞個AOP掃controller包下所有介面,獲取入參,將其列印出來。介面的回傳不知道你能否拿到uj5u.com熱心網友回復:
小白不會寫 需要代碼示范怎么攔截spring的請求通道
uj5u.com熱心網友回復:
像樓上兄弟說的那樣,做個AOP吧,下面的只是測驗參考,需要的資訊基本都在請求行里面。樓主要這個做什么啊?訪問日志做統計?還是有其他用處啊,有些資訊在access log上面是有的,或者nginx上的日志package org.outerwaterfire.springweb_test.web;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/Hello")
public class TestController {
@RequestMapping("/haha")
public String haha(HttpServletRequest httpServletRequest) {
Map<String, String> headers = new HashMap<>();
Enumeration headerNames = httpServletRequest.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
headers.put(headerName, httpServletRequest.getHeader(headerName));
}
headers.put("method",httpServletRequest.getMethod());
headers.put("protocol",httpServletRequest.getProtocol());
Gson gson = new GsonBuilder().create();
System.out.println("headers====" + gson.toJson(headers));
return "done";
}
}
uj5u.com熱心網友回復:
就是為了除錯的時候方便,這個我不會寫
1. 不知道怎么獲取input output stream
2. 這個stream只能讀寫一次 攔截了肯定影響正常的spring rest controller決議,怎么解決不可重復讀也是問題
3. controller我會寫,aspect我也會寫我是不懂spring,不知道怎么攔截,攔截到了也不會解決stream不可重復讀寫問題
uj5u.com熱心網友回復:
這套我已經實作了,但這套每個method都要加,麻煩 想通過aop解決會衍生其他問題
uj5u.com熱心網友回復:
可以在每個method上添加@Action 注解, 然后用切面類來實作。
uj5u.com熱心網友回復:
這樣太麻煩了,用filter實作了
package com.ximalaya.xmkp.im.utils.web.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
@Slf4j
@Component
public class WebLogFilter extends OncePerRequestFilter implements Ordered {
// put filter at the end of all other filters to make sure we are processing after all others
private int order = Ordered.LOWEST_PRECEDENCE - 8;
@Override
public int getOrder() {
return order;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
ContentCachingRequestWrapper wrapperRequest = new ContentCachingRequestWrapper(request);
ContentCachingResponseWrapper wrapperResponse = new ContentCachingResponseWrapper(response);
filterChain.doFilter(wrapperRequest, wrapperResponse);
//dump context
String requestRaw = dumpRequest(wrapperRequest);
log.info("raw request :" + requestRaw);
String responseRaw = dumpResponse(wrapperResponse);
log.info("raw response :" + responseRaw);
wrapperResponse.copyBodyToResponse();
}
private String dumpRequest(ContentCachingRequestWrapper request){
if(request == null) {
return "";
}
ArrayList<String> results = new ArrayList<>();
results.add("");
results.add(request.getMethod() + " " + request.getRequestURI() + "?" + request.getQueryString() + " " + request.getProtocol());
for(Enumeration<String> names = request.getHeaderNames(); names.hasMoreElements();){
String head = names.nextElement().toString();
results.add(head + ": " + request.getHeader(head));
}
results.add("");
results.add(getRequestBody(request));
return String.join("\n", results);
}
private String dumpResponse(ContentCachingResponseWrapper response){
if(response == null) {
return "";
}
ArrayList<String> results = new ArrayList<>();
results.add("");
results.add("" + response.getStatusCode());
for (String head: response.getHeaderNames()) {
results.add(head + ": " + response.getHeader(head));
}
results.add("Content-Type: " + response.getContentType());
results.add("Content-Length: " + response.getContentSize());
results.add("Charset-Encoding: " + response.getCharacterEncoding());
results.add("Locale: " + response.getLocale());
results.add("");
results.add(getResponseBody(response));
return String.join("\n", results);
}
private String getRequestBody(ContentCachingRequestWrapper request) {
if(request != null) {
byte[] buf = request.getContentAsByteArray();
if(buf.length > 0) {
String payload;
try {
payload = new String(buf, 0, buf.length, request.getCharacterEncoding());
} catch (UnsupportedEncodingException e) {
payload = "[unknown]";
}
return payload;
}
}
return "";
}
private String getResponseBody(ContentCachingResponseWrapper response) {
if(response != null) {
byte[] buf = response.getContentAsByteArray();
if(buf.length > 0) {
String payload;
try {
payload = new String(buf, 0, buf.length, response.getCharacterEncoding());
} catch (UnsupportedEncodingException e) {
payload = "[unknown]";
}
return payload;
}
}
return "";
}
}
uj5u.com熱心網友回復:
這種一般過濾器做,aop并不是服務的最外層,當然一般情況下,你可以考慮修改容器的access log的日志級別轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/267734.html
標籤:Web 開發
