欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

request.getInputStream以流的方式读取请求只能读取一次

程序员文章站 2022-03-10 11:52:25
...

当项目上用了 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":""
}
 

转载于:https://my.oschina.net/lvzi98/blog/2980786