#可重复读 Request RepeatedlyRequestWrapper

开源项目 RequestWrapper 内部stream读取后就没了。


// 我们无法两次读取相同的InputStream 它是原始HttpServletRequest对象的包装。 当我们读取请求正文时,ContentCachingRequestWrapper会缓存内容供以后使用。 // requestWrapper.getContentAsByteArray()必须是在request.inputStream()的内容使用过后才能缓存请求中body的内容, // 下次需要再使用body只能使用此方法requestWrapper.getContentAsByteArray()才能再次获取body中的值。 // https://www.jianshu.com/p/977372059ae7

// OncePerRequestFilter 中
     ContentCachingRequestWrapper wrapperRequest = new ContentCachingRequestWrapper(request);
        ContentCachingResponseWrapper wrapperResponse = new ContentCachingResponseWrapper(response);
        chain.doFilter(wrapperRequest, wrapperResponse);

这里另一种方式,一直可以读。但这个流、缓存 对性能,内存有一定影响,大量请求时候

package org.javaboy.tienchin.common.filter;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.javaboy.tienchin.common.utils.http.HttpHelper;

/**
 * 构建可重复读取inputStream的request
 *
 * @author tienchin
 */
public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper {
    private final byte[] body;

    public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException {
        super(request);
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");

        body = HttpHelper.getBodyString(request).getBytes("UTF-8");
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return bais.read();
            }

            @Override
            public int available() throws IOException {
                return body.length;
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }
}