1. 程式人生 > >request.getInputStream以流的方式讀取請求只能讀取一次

request.getInputStream以流的方式讀取請求只能讀取一次

當專案上用了 request.getInputStream以流的方式讀取請求,而實際專案中一般會用到一些攔截器,做一些校驗,發現只能讀取一次,真正到Controller裡,發現是不能用的。

比如,前端請求時以json方式提交 ,後臺用用@RequestBody或者用流 做json到物件的解析,這時這個json串裡有個引數要放在攔截器裡校驗一下

在攔截器裡以流的形式讀取了,後臺這就取不到引數

解決辦法,網上好多人是加了個過濾器,把請求包裝一下,



import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

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

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest) {
            requestWrapper = new SdHttpServletWrapper((HttpServletRequest) request);
        }
        if (null == requestWrapper) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }

    @Override
    public void destroy() {

    }

}



import org.apache.commons.lang.StringUtils;

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 SdHttpServletWrapper extends HttpServletRequestWrapper {
    private final byte[] body;

    public SdHttpServletWrapper(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() throws IOException {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {

            @Override
            public int read() throws IOException {
                return bais.read();
            }
        };
    }

    /**
     * 通過BufferedReader和字元編碼集轉換成byte陣列
     *
     * @param br
     * @param encoding
     * @return
     * @throws IOException
     */
    private byte[] readBytes(BufferedReader br, String encoding) throws IOException {
        String str = null, retStr = "";
        while ((str = br.readLine()) != null) {
            retStr += str;
        }
        if (StringUtils.isNotBlank(retStr)) {
            return retStr.getBytes(Charset.forName(encoding));
        }
        return null;
    }


}
	<filter>
		<filter-name>springFilter</filter-name>
		<filter-class> com.XXXXX.RequestFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>springFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

還有一種辦法就是前端請求時,把要校驗的引數,拼到url後面,這樣後臺這可以同時用@RequestBody 和request.getparametere獲取引數

POST /srs/manage/sysparam/query?token=dsfdsfsdfsdfs HTTP/1.1
Host: srs.xxx.com
Content-Type: application/json
Cache-Control: no-cache
Postman-Token: a52c36d2-d42d-4fc5-3132-8ad03dd65a08

 {"classCode":"srs.txn.type",
    "code":"P",
    "name":""
}