HttpServletRequest.getInputStream()只能读取一次

HttpServletRequest.getInputStream只能读取一次

    • 1.覆写HttpServletRequestWrapper的getInputStream(),getReader().新建下如下类继承HttpServletRequestWrapper
    • 2.filter中的代码块如下,即使filter中已经获取过一次之后,chain.doFilter(request, response)也不会有错误了
    • 3.如果还有问题的话,就只能再下面留言了吧

问题描述 : 在开发一支API时因为需要在filter中取出request body中的内容进行加密,进行chain.doFilter(request, response);
之后的endpoint处理时 body中的内容为null

问题原因 : HttpServletRequest.getInputStream()只能读取一次,好似一杯水在filter里已经倒掉了,后面再用就没有了

解决办法 : 如下

1.覆写HttpServletRequestWrapper的getInputStream(),getReader().新建下如下类继承HttpServletRequestWrapper

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.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class MyRequestWrapper extends HttpServletRequestWrapper {
    private final String body;
    public MyRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        StringBuilder sb = new StringBuilder();
        String line;
        BufferedReader reader = request.getReader();
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }
        body = sb.toString();
    }
    
    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body.getBytes());
        return new ServletInputStream() {
            @Override
            public int read() throws IOException {
                return bais.read();
            }

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

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

			@Override
			public void setReadListener(ReadListener readListener) {
			}
        };
    }

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

2.filter中的代码块如下,即使filter中已经获取过一次之后,chain.doFilter(request, response)也不会有错误了

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import platform.config.APIGatewaySign;

public class OpenAPIFilter implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// 转换成自己覆写的类
		MyRequestWrapper req = new MyRequestWrapper((HttpServletRequest)request);
		// req.getInputStream()
		ServletInputStream inStream = req.getInputStream();
		
		// 如果没有覆写HttpServletRequestWrapper
		// doFilter(request, response)之后 再用到body
		//会抛出类似错误 Cannot call getInputStream(), getReader() already called
		chain.doFilter(request, response);
	}
	@Override
	public void destroy() {

	}
	
}

3.如果还有问题的话,就只能再下面留言了吧

你可能感兴趣的:(code)