打印信息格式:
前端信息
后端信息
springboot下配置
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
@Configuration
public class LoggingFilterConfig implements Filter {
private static final Logger logger = LoggerFactory.getLogger(LoggingFilterConfig.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
Map<String, Object> map = new HashMap<String, Object>();
HttpServletRequest requestWrapper = null;
// LogPosition使用时间戳作为日志的定位数字,在idea的控制台中使用Ctrl+f调出查询框,
// 让前端将异常接口的LogPosition发给后端,后端即可快速定位错误接口
String time = String.valueOf(new Date().getTime());
res.setHeader("LogPosition",time);
map.put("LogPosition",time);
try {
// Get request URL.
map.put("URL", req.getRequestURL());
map.put("Method", req.getMethod());
map.put("Protocol", req.getProtocol());
map.put("RemoteAddr", req.getRemoteAddr());
map.put("RemoteHost", req.getRemoteHost());
// 获取header信息
List<Map<String, String>> headerList = new ArrayList<>();
Map<String, String> headerMaps = new HashMap<>();
for (Enumeration<String> enu = req.getHeaderNames(); enu.hasMoreElements(); ) {
String name = enu.nextElement();
headerMaps.put(name, req.getHeader(name));
}
headerList.add(headerMaps);
map.put("Headers", headerList);
//获取parameters信息
List<Map<String, String>> parameterList = new ArrayList<>();
Map<String, String> parameterMaps = new HashMap<>();
for (Enumeration<String> names = req.getParameterNames(); names.hasMoreElements(); ) {
String name = names.nextElement();
parameterMaps.put(name, req.getParameter(name));
}
parameterList.add(parameterMaps);
map.put("parameters", parameterList);
// 获取请求体信息,一般为json,此处慎用,传输文件时ContentType不包含multipart报跨域
// 其它情况暂未发现,如发现一直报错未解决,可以先把这两个日志拦截处理文件先删除
String reqContentType = req.getContentType();
HashMap<Object, Object> contextMap = new HashMap<>();
System.out.println(reqContentType);
if (reqContentType != null){
if (!reqContentType.contains("multipart")){
requestWrapper = new RepeatedlyReadRequestWrapper(req);
String line = "";
if (req.getMethod().equalsIgnoreCase("POST")) {
int len = req.getContentLength();
char[] buf = new char[len];
int bufcount = requestWrapper.getReader().read(buf);
if (len > 0 && bufcount <= len) {
line = String.copyValueOf(buf).substring(0, bufcount);
}
} else if (req.getMethod().equalsIgnoreCase("GET")) {
int idx = req.getRequestURL().indexOf("?");
if (idx != -1) {
line = req.getRequestURL().substring(idx + 1);
} else {
line = null;
}
}
if (line != null) {
contextMap.put("Context", new String[]{line});
}
}
}
//打印日志信息
JSONObject context = JSONObject.fromObject(contextMap);
String strContext = context.toString();
String substring = "";
if(strContext.length() >= 14){
substring = context.toString().substring(12, strContext.length() - 2);
}
System.out.println();
logger.info("URL:" + map.get("URL"));
logger.info("LogPosition:" + map.get("LogPosition"));
logger.info("RemoteHost:" + map.get("RemoteHost"));
logger.info("Method:" + map.get("Method"));
logger.info(substring);
//这里输出一个回车的作用是便于复制Context的json,在浏览器搜索json找一个在线解析json的网站,复制丢进去
System.out.println();
if (requestWrapper == null){
chain.doFilter(request, response);
}else {
chain.doFilter(requestWrapper, response);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public void destroy() {
}
}
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
public class RepeatedlyReadRequestWrapper extends HttpServletRequestWrapper {
private final byte[] body;
public RepeatedlyReadRequestWrapper(HttpServletRequest request)
throws IOException {
super(request);
body = readBytes(request.getReader(), "UTF-8");
}
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
}
@Override
public int read() {
return bais.read();
}
};
}
/**
* 通过BufferedReader和字符编码集转换成byte数组
*/
private byte[] readBytes(BufferedReader br, String encoding) throws IOException {
String str = null, retStr = "";
while ((str = br.readLine()) != null) {
retStr += str;
}
//StringUtil.isNotNull可以自己实现也可以用第三方或自带的,其作用是判断入参是否为空串
if (StringUtil.isNotNull(retStr)) {
return retStr.getBytes(Charset.forName(encoding));
}
return null;
}
}