去年在開放中遇到過一個問題,因?yàn)轫?xiàng)目重構(gòu)筋蓖,數(shù)據(jù)庫等完全的重構(gòu)卸耘,所以線上產(chǎn)生了兩套環(huán)境。由于我們做的是開放平臺粘咖,已經(jīng)有很多開發(fā)者對接了蚣抗,所以老的服務(wù)需要保留,一時間需要維護(hù)兩套服務(wù)瓮下,老服務(wù)中很多應(yīng)用遇到問題翰铡,無法修改應(yīng)用信息,需要聯(lián)系客服然后我們手動修改讽坏,非常麻煩锭魔。于是項(xiàng)目組決定將老的數(shù)據(jù)訂正到新的表中,然后在老的服務(wù)中做一次向上的轉(zhuǎn)發(fā)路呜,如果失敗了再走老的平臺迷捧。所以需要重復(fù)讀取HTTP請求的body數(shù)據(jù),團(tuán)隊(duì)leader給了思路胀葱,寫一個request的包裝類漠秋,將讀到的inputstream緩存到內(nèi)存中,便可以重復(fù)讀取抵屿。先上代碼:
import org.apache.commons.io.IOUtils;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
/**
* HttpServletRequestWrapper的包裝類膛堤,用于重復(fù)讀取inputStream
*
* Created by yuanjian on 10/17/17
* @author liuyj@shinemo.com
*/
public class InputStreamReadRepeatableRequestWrapper extends HttpServletRequestWrapper {
private ServletInputStream inputStream;
public InputStreamReadRepeatableRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (this.getContentLength() < 1) {
return null;
}
if (this.inputStream == null) {
this.inputStream = new InputStreamReadRepeatableRequestWrapper.ReadRepeatableInputStream(this.getRequest().getInputStream(), this.getRequest().getContentLength());
}
return inputStream;
}
private class ReadRepeatableInputStream extends ServletInputStream {
private final ByteArrayInputStream bi;
private ReadRepeatableInputStream(ServletInputStream inputStream, int length) throws IOException {
if (length > 0) {
byte[] bytes = new byte[length];
IOUtils.read(inputStream, bytes, 0, length);
inputStream.read(bytes, 0, length);
bi = new ByteArrayInputStream(bytes, 0, length);
} else {
bi = null;
}
}
@Override
public int read() throws IOException {
int bt = -1;
if (bi != null) {
bt = this.bi.read();
if (bt == -1) {
this.bi.reset();
}
}
return bt;
}
@Override
public void reset() {
this.bi.reset();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
}
}
然后新增一個filter
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @author liuyj@shinemo.com
*/
public final class RequestFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
InputStreamReadRepeatableRequestWrapper request = new InputStreamReadRepeatableRequestWrapper((HttpServletRequest) servletRequest);
filterChain.doFilter(request, servletResponse);
}
@Override
public void destroy() {
}
}
最后只需要在web.xml中配置此filter即可。