请求日志——用于调试开发

我就是我 2022-04-13 04:57 211阅读 0赞

一、前言

在请求分发给具体的处理器之前,我们可以通过过滤器和拦截器来截取请求信息,但是藏于body中的参数确不能直接获取,因为在流对象中只允许一次性打开,这就好比你将桶里的水倒干净了,然后把桶交给别人。

常规的处理方案有两种:

  1. 1、将流内容导入另一个流,然后将新的流传递
  2. 2、通过mark()和reset()方法将流内容回流。

最初,我采用第二种方式,却发现依旧存在很多问题,比如mark长度难以确定,无法绕开servletRequest无法二次打开的设定。于是采用第一种办法。

二、如何复制请求流

  1. package com.baye.common.core.filter;
  2. import org.apache.commons.lang.StringUtils;
  3. import javax.servlet.ReadListener;
  4. import javax.servlet.ServletInputStream;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletRequestWrapper;
  7. import java.io.BufferedReader;
  8. import java.io.ByteArrayInputStream;
  9. import java.io.IOException;
  10. import java.io.InputStreamReader;
  11. import java.nio.charset.Charset;
  12. /**
  13. * 复制请求,代替原有request传递给具体处理器
  14. *
  15. * @author sunyiran
  16. * @date 2018-11-27
  17. */
  18. public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
  19. /**
  20. * 利用body存储流内容
  21. */
  22. private final byte[] body;
  23. public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
  24. super(request);
  25. body = readBytes(request.getReader());
  26. }
  27. @Override
  28. public BufferedReader getReader() throws IOException {
  29. return new BufferedReader(new InputStreamReader(getInputStream()));
  30. }
  31. @Override
  32. public ServletInputStream getInputStream() throws IOException {
  33. final ByteArrayInputStream bais = new ByteArrayInputStream(body);
  34. return new ServletInputStream() {
  35. @Override
  36. public boolean isFinished() {
  37. return false;
  38. }
  39. @Override
  40. public boolean isReady() {
  41. return false;
  42. }
  43. @Override
  44. public void setReadListener(ReadListener readListener) {
  45. }
  46. @Override
  47. public int read() throws IOException {
  48. return bais.read();
  49. }
  50. };
  51. }
  52. /**
  53. * 通过BufferedReader和字符编码集转换成byte数组
  54. *
  55. * @param br
  56. * @return
  57. * @throws IOException
  58. */
  59. private byte[] readBytes(BufferedReader br ) throws IOException {
  60. String str;
  61. StringBuilder retStr = new StringBuilder();
  62. while ((str = br.readLine()) != null) {
  63. retStr.append(str);
  64. }
  65. if (StringUtils.isNotBlank(retStr.toString())) {
  66. return retStr.toString().getBytes(Charset.forName("utf-8"));
  67. }
  68. return null;
  69. }
  70. }

三、如何过滤请求

注意在主类上添加:@ServletComponentScan

  1. package com.baye.common.core.filter;
  2. import org.apache.commons.lang.StringUtils;
  3. import org.apache.commons.logging.Log;
  4. import org.apache.commons.logging.LogFactory;
  5. import javax.servlet.*;
  6. import javax.servlet.annotation.WebFilter;
  7. import javax.servlet.http.HttpServletRequest;
  8. import java.io.BufferedReader;
  9. import java.io.IOException;
  10. import java.util.Enumeration;
  11. import java.util.Map;
  12. /**
  13. * todo 上线时关闭
  14. * @author sunyiran
  15. * @date 2018-11-27
  16. */
  17. @WebFilter(urlPatterns = "/*")
  18. public class RequestLogFilter implements Filter{
  19. private static final Log logger = LogFactory.getLog("RequestLogdFilter");
  20. @Override
  21. public void destroy() {
  22. }
  23. @Override
  24. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  25. throws IOException, ServletException {
  26. ServletRequest requestWrapper = printRequestLog((HttpServletRequest) request);
  27. if (requestWrapper == null) {
  28. chain.doFilter(request,response);
  29. }
  30. chain.doFilter(requestWrapper, response);
  31. }
  32. @Override
  33. public void init(FilterConfig arg0) {
  34. }
  35. /**
  36. * 打印请求详情
  37. * @param request
  38. * @return
  39. * @throws IOException
  40. */
  41. private ServletRequest printRequestLog(HttpServletRequest request) throws IOException {
  42. Map<String, String[]> params = request.getParameterMap();
  43. String requestUri = request.getRequestURI();
  44. String ip = getRemoteHost(request);
  45. StringBuilder msg = new StringBuilder(
  46. "\r\n" + ip + "-请求:" + requestUri + "-->[" + request.getMethod() + "]\r\n");
  47. Enumeration<String> headers = request.getHeaderNames();
  48. String key = null;
  49. while (headers.hasMoreElements()) {
  50. key = headers.nextElement();
  51. msg.append("\t").append(key).append(":\t\t").append(request.getHeader(key)).append("\r\n");
  52. }
  53. msg.append("---------------------------------------------------------------------------------\r\n");
  54. //如果传递方式为RequestParam
  55. if (params != null && !params.isEmpty()) {
  56. msg.append("\tRequestParam:");
  57. for (Map.Entry<String, String[]> item : params.entrySet()) {
  58. msg.append("\t").append(item.getKey()).append(":\t\t").append(StringUtils.join(item.getValue(), "/"))
  59. .append("\r\n");
  60. }
  61. logger.info(msg.toString());
  62. return request;
  63. }
  64. //如果传递方式为RequestBody
  65. msg.append("\r\n\tRequestBody:");
  66. if (request.getContentLength() > 0) {
  67. request = new BodyReaderHttpServletRequestWrapper(request);
  68. }else {
  69. logger.info(msg.toString());
  70. return request;
  71. }
  72. BufferedReader br = request.getReader();
  73. String str ;
  74. StringBuilder retStr= new StringBuilder();
  75. while ((str = br.readLine()) != null) {
  76. retStr.append(str);
  77. }
  78. msg.append(retStr);
  79. logger.info(msg.toString());
  80. return request;
  81. }
  82. /**
  83. * 获取请求主机地址
  84. * @param request
  85. * @return
  86. */
  87. public String getRemoteHost(HttpServletRequest request) {
  88. String ip = request.getHeader("x-forwarded-for");
  89. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  90. ip = request.getHeader("Proxy-Client-IP");
  91. }
  92. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  93. ip = request.getHeader("WL-Proxy-Client-IP");
  94. }
  95. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  96. ip = request.getRemoteAddr();
  97. }
  98. return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
  99. }
  100. }

四、请求测试

watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1ODEzNjUz_size_16_color_FFFFFF_t_70

发表评论

表情:
评论列表 (有 0 条评论,211人围观)

还没有评论,来说两句吧...

相关阅读

    相关 syslog日志接口调试方法

    日志数据采集,比较方便常用的就是通过syslog来进行数据采集,syslog可以通过udp协议来进行高效的数据传输。一般来说在工程实施的过程中需要对接对端系统的数据采集源可以通

    相关 USB调试日志乱码

    之前一直用  adb logcat -v time>E:log.txt 把USE调试的日志输出到指定文件 这两天输出的日志忽然间乱码了 百度了一下,解决方案特别

    相关 请求日志——用于调试开发

    一、前言 在请求分发给具体的处理器之前,我们可以通过过滤器和拦截器来截取请求信息,但是藏于body中的参数确不能直接获取,因为在流对象中只允许一次性打开,这就好比你将桶里