创建一个扩展 HttpServletRequestWrapper 的类。此类将原始请求的输入流上的内容缓存在临时文件中。
public class CachedHttpServletRequest extends HttpServletRequestWrapper
{
public static final String TEMPORARY_FILENAME_PREFIX = "MyPrefix";
public static final String TEMPORARY_FILENAME_SUFFIX = ".cache";
public static final int LEN_BUFFER = 32768; //32 KB
private File m_TemporaryFile;
public CachedHttpServletRequest(HttpServletRequest httpServletRequest, File temporaryFolder)
throws ServletException {
super(httpServletRequest);
try {
//Create a temporary file to hold the contents of the request's input stream
m_TemporaryFile = File.createTempFile(TEMPORARY_FILENAME_PREFIX, null, temporaryFolder);
//Copy the request body to the temporary file
BufferedInputStream is = new BufferedInputStream(super.getInputStream());
FileOutputStream os = new FileOutputStream(m_TemporaryFile);
byte[] buffer = new byte[LEN_BUFFER];
int bytesWritten = 0;
int bytesRead = is.read(buffer);
while(bytesRead != -1) {
os.write(buffer, 0, bytesRead);
bytesWritten += bytesRead;
bytesRead = is.read(buffer);
}
is.close();
os.close();
}
catch(Exception e) {
throw new ServletException(e);
}
}
public void cleanup() {
m_TemporaryFile.delete();
}
@Override
public ServletInputStream getInputStream() throws IOException {
return new CachedServletInputStream(m_TemporaryFile);
}
@Override
public BufferedReader getReader() throws IOException {
String enc = getCharacterEncoding();
if(enc == null) enc = "UTF-8";
return new BufferedReader(new InputStreamReader(getInputStream(), enc));
}
}
创建一个扩展 ServletInputStream 的类。当调用 getInputStream() 或 getReader() 时,您的请求包装类将返回此自定义输入流的实例。自定义输入流类将使用临时文件打开缓存的内容。
public class CachedServletInputStream extends ServletInputStream {
private File m_TemporaryFile;
private InputStream m_InputStream;
public CachedServletInputStream(File temporaryFile) throws IOException {
m_TemporaryFile = temporaryFile;
m_InputStream = null;
}
private InputStream acquireInputStream() throws IOException {
if(m_InputStream == null) {
m_InputStream = new FileInputStream(m_TemporaryFile);
}
return m_InputStream;
}
public void close() throws IOException {
try {
if(m_InputStream != null) {
m_InputStream.close();
}
}
catch(IOException e) {
throw e;
}
finally {
m_InputStream = null;
}
}
public int read() throws IOException {
return acquireInputStream().read();
}
public boolean markSupported() {
return false;
}
public synchronized void mark(int i) {
throw new UnsupportedOperationException("mark not supported");
}
public synchronized void reset() throws IOException {
throw new IOException(new UnsupportedOperationException("reset not supported"));
}
}
创建一个实现 javax.servlet.Filter 的类,该类在检测到需要缓存输入流行为的请求时实例化您的自定义请求包装器。
public class CachedHttpServletRequestFilter implements Filter {
public static final String HTTP_HEADER_CONTENT_TYPE = "Content-Type";
public static final String MIME_APPLICATION__X_WWW_FORM_URL_ENCODED = "application/x-www-form-urlencoded";
private File m_TemporaryFolder;
public CachedHttpServletRequestFilter() {
m_TemporaryFolder = new File(/*...your temporary directory goes here...*/);
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
if(servletRequest instanceof HttpServletRequest) {
HttpServletRequest request = (HttpServletRequest) servletRequest;
// Check wether the current request needs to be able to support the body to be read multiple times
String contentType = StringHelper.getLowercaseTrimmed(request.getHeader(HTTP_HEADER_CONTENT_TYPE));
if(contentType.equals(MIME_APPLICATION__X_WWW_FORM_URL_ENCODED)) {
// Override current HttpServletRequest with custom implementation
CachedHttpServletRequest cachedRequest = new CachedHttpServletRequest(request, m_TemporaryFolder);
filterChain.doFilter(cachedRequest, servletResponse);
cachedRequest.cleanup();
return;
}
}
filterChain.doFilter(servletRequest, servletResponse);
}
public void init(FilterConfig filterConfig) throws ServletException {
try {
/* ...initialize where your temporary folder is located here... */
//m_TemporaryFolder = new File(/*...*/);
}
catch(Exception e) {
throw new ServletException(e);
}
}
public void destroy() {
}
}