记录HttpRequest参数和请求正文

| 我正在尝试为我的Web应用程序创建请求日志。我正在使用Spring 3。 0。 我实现了扩展
HandlerInterceptorAdapter
的类,并使用
preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
拦截请求。 在该方法中,我希望能够记录请求正文(我的参数是直接写入请求正文的XML对象),为此,我使用
request.getReader();
问题是-稍后,当弹簧控制器尝试读取请求时,我会得到一个
IllegalStateException
。 有什么办法可以实现我的预期?     
已邀请:
        您可以使用过滤器执行此操作。请求参数易于处理。 但是,处理请求主体将更加困难 并且需要包装servlet请求,请参见:HttpServletRequest。 您将需要查看传入的请求有多大,并确定是将请求正文存储为tmp文件还是字符串。 您将需要使用用于日志记录的文件或保存的字符串覆盖ServetRequest.getInputStream()。 如果请求主体很大,我建议将输入流放入缓冲的输入流中,然后读取主体的开头。
public class LogRequest extends HttpServletRequestWrapper {

    public LogRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        //read from tmp file or string.
    }

    @Override
    public BufferedReader getReader() throws IOException {
        //read from tmp file or string
    }

}
    
        Spring有一个现成的过滤器可以为您完成此任务-请参阅此答案中所描述的
AbstractRequestLoggingFilter
及其子类的用法。 请注意,使用此解决方案时,仅在请求处理完成并且您的应用程序已读取请求正文之后,才会记录请求正文。     
        小型请求的简单实现。不要将其用于多部分请求。
package ru.rbs.logger.web;

import org.apache.commons.io.IOUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

class CachedRequestWrapper extends HttpServletRequestWrapper {
    private final byte[] cachedBody;

    CachedRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        IOUtils.copy(request.getInputStream(), bos);
        cachedBody = bos.toByteArray();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new CachedServletInputStream();
    }

    byte[] toByteArray(){
        return cachedBody;
    }

    private class CachedServletInputStream extends ServletInputStream {
        private InputStream baseInputStream;

        CachedServletInputStream() throws IOException {
            baseInputStream = new ByteArrayInputStream(cachedBody);
        }

        @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 baseInputStream.read();
        }
    }
}
    

要回复问题请先登录注册