package art.kexue.sxwz.interceptor; import jakarta.servlet.ReadListener; import jakarta.servlet.ServletInputStream; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequestWrapper; import java.io.*; /** * 可重复读取请求体的 HttpServletRequest 包装类 * * @author 王志维 * @since 2026-04-14 */ public class CachedBodyHttpServletRequest extends HttpServletRequestWrapper { private final byte[] cachedBody; public CachedBodyHttpServletRequest(HttpServletRequest request) throws IOException { super(request); // 读取并缓存请求体 this.cachedBody = readBytes(request.getInputStream()); } @Override public ServletInputStream getInputStream() { return new CachedBodyServletInputStream(this.cachedBody); } @Override public BufferedReader getReader() { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.cachedBody); return new BufferedReader(new InputStreamReader(byteArrayInputStream)); } /** * 获取缓存的请求体字符串 */ public String getCachedBodyString() { return new String(cachedBody); } /** * 从输入流读取字节数组 */ private byte[] readBytes(InputStream inputStream) throws IOException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[1024]; while ((nRead = inputStream.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } return buffer.toByteArray(); } /** * 可重复读取的 ServletInputStream */ private static class CachedBodyServletInputStream extends ServletInputStream { private final ByteArrayInputStream inputStream; public CachedBodyServletInputStream(byte[] cachedBody) { this.inputStream = new ByteArrayInputStream(cachedBody); } @Override public boolean isFinished() { return inputStream.available() == 0; } @Override public boolean isReady() { return true; } @Override public void setReadListener(ReadListener listener) { throw new UnsupportedOperationException(); } @Override public int read() { return inputStream.read(); } } }