由于在zuul中請求的request.getInputStream()律适,只能讀取一次管怠,所以在分析請求內(nèi)容后,會關(guān)閉stream流亏掀,所以后續(xù)無法獲取忱反。
這里給出解決方法核心為重寫request。
1幌氮、 單獨(dú)項(xiàng)目使用
例如filter中獲取一次請求以后body缭受,我們在controller想再次獲取請求body。request.getInputStream()返回的是ServletInputStream该互,此方法沒有實(shí)現(xiàn)流的mark/reset方法米者,我們在filter中讀取以后無法對流進(jìn)行復(fù)位
*BodyReaderHttpServletRequestWrapper .java
代碼實(shí)現(xiàn)如下:
public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {
private byte[] body;
public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
try {
body = StreamUtils.getByteByStream(request.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public BufferedReader getReader() {
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream bais = new ByteArrayInputStream(body);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() {
return bais.read();
}
};
}
}
- StreamUtils.java
public class StreamUtils {
public static byte[] getByteByStream(InputStream is) throws Exception {
byte[] buffer = new byte[1024];
int len = 0;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
while ((len = is.read(buffer)) != -1) {
bos.write(buffer, 0, len);
}
bos.flush();
return bos.toByteArray();
}
}
- 使用:
- filter 中使用
public class MyFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest arg0, ServletResponse response, FilterChain chain) throws IOException, ServletException {
// TODO Auto-generated method stub
HttpServletRequest request = (HttpServletRequest) arg0;
ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request);
//測試在filter中獲取一次
InputStream is = requestWrapper.getInputStream();
String body = IOUtils.toString(inp);
// 關(guān)閉文件輸入流
is.close();
// 關(guān)閉輸出流
out.close();
chain.doFilter(requestWrapper, response);
}
public void init(FilterConfig arg0) throws ServletException {
}
}
- controller中使用
@RequestMapping(value="/test",method=RequestMethod.POST) public void downloadsql(HttpServletRequest request, HttpServletResponse response){
//正常使用即可
}
2、 zuul中使用,和filter類似
- 增加一個前置過濾器
public class PreRequest extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
return FORM_BODY_WRAPPER_FILTER_ORDER +1;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext.getCurrentContext().setRequest(new BodyReaderHttpServletRequestWrapper( RequestContext.getCurrentContext().getRequest()) );
return null;
}
}
- controller 和上面相同即可