Skip to content

Instantly share code, notes, and snippets.

@vamdt
Last active January 18, 2024 06:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vamdt/8cef782411345969902f4da8ae14866e to your computer and use it in GitHub Desktop.
Save vamdt/8cef782411345969902f4da8ae14866e to your computer and use it in GitHub Desktop.
兼容各种请求格式的重复读HttpServletRequestWrapper
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.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.*;
public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
private byte[] bodyBytes;
private final ByteArrayOutputStream cachedContent;
public ContentCachingRequestWrapper(HttpServletRequest request) throws IOException {
super(request);
int contentLength = request.getContentLength();
this.cachedContent = new ByteArrayOutputStream(contentLength >= 0 ? contentLength : 1024);
System.out.printf("cacheContent:%s", this.cachedContent.toString());
//设置读取编码
this.setCharacterEncoding("UTF-8");
// 读取数据 form data
this.getParameterMap();
System.out.println("parametermap:" + this.getParameterMap());
this.bodyBytes = this.cachedContent.toByteArray();
System.out.println("bodyBytes1:" + new String(this.bodyBytes));
// 如果form-data 读取不到, 读取stream
if (this.bodyBytes.length == 0) {
try {
this.bodyBytes = IOUtils.toByteArray(super.getInputStream());
} catch (Throwable ex) {
ex.printStackTrace();
this.bodyBytes = new byte[0];
}
}
System.out.println("bodyBytes2:" + new String(this.bodyBytes));
}
@Override
public String getCharacterEncoding() {
String enc = super.getCharacterEncoding();
return (enc != null ? enc : "UTF-8");
}
// 重新读取字节数组
@Override
public ServletInputStream getInputStream() throws IOException {
return new ContentCachingInputStream(this.bodyBytes);
}
// 重新读取字节数组
@Override
public BufferedReader getReader() throws IOException {
return new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
}
@Override
public String getParameter(String name) {
if (this.cachedContent.size() == 0 && isFormPost()) {
writeRequestParametersToCachedContent();
}
return super.getParameter(name);
}
@Override
public Map<String, String[]> getParameterMap() {
if (this.cachedContent.size() == 0 && isFormPost()) {
writeRequestParametersToCachedContent();
}
return super.getParameterMap();
}
@Override
public Enumeration<String> getParameterNames() {
if (this.cachedContent.size() == 0 && isFormPost()) {
writeRequestParametersToCachedContent();
}
return super.getParameterNames();
}
@Override
public String[] getParameterValues(String name) {
if (this.cachedContent.size() == 0 && isFormPost()) {
writeRequestParametersToCachedContent();
}
return super.getParameterValues(name);
}
private boolean isFormPost() {
return "post".equalsIgnoreCase(getMethod());
}
private void writeRequestParametersToCachedContent() {
try {
if (this.cachedContent.size() == 0) {
String requestEncoding = getCharacterEncoding();
Map<String, String[]> form = super.getParameterMap();
for (Iterator<String> nameIterator = form.keySet().iterator(); nameIterator.hasNext(); ) {
String name = nameIterator.next();
List<String> values = Arrays.asList(form.get(name));
for (Iterator<String> valueIterator = values.iterator(); valueIterator.hasNext(); ) {
String value = valueIterator.next();
this.cachedContent.write(URLEncoder.encode(name, requestEncoding).getBytes());
if (value != null) {
this.cachedContent.write('=');
this.cachedContent.write(URLEncoder.encode(value, requestEncoding).getBytes());
if (valueIterator.hasNext()) {
this.cachedContent.write('&');
}
}
}
if (nameIterator.hasNext()) {
this.cachedContent.write('&');
}
}
}
}
catch (IOException ex) {
throw new IllegalStateException("Failed to write request parameters to cached content", ex);
}
}
public String getBodyAsString(String encoding) throws UnsupportedEncodingException {
String bodyStr = new String(this.bodyBytes, encoding);
// url 解码
bodyStr = URLDecoder.decode(bodyStr, encoding);
return bodyStr;
}
private class ContentCachingInputStream extends ServletInputStream {
private final InputStream is;
private boolean isFinished = false;
public ContentCachingInputStream(byte[] content) {
this.is = new ByteArrayInputStream(content);
}
@Override
public int read() throws IOException {
int read = this.is.read();
if (read == -1) {
this.isFinished = true;
}
return read;
}
@Override
public int read(byte[] b) throws IOException {
int read = this.is.read(b);
if (read == -1) {
this.isFinished = true;
}
return read;
}
@Override
public int read(final byte[] b, final int off, final int len) throws IOException {
int read = this.is.read(b, off, len);
if (read == -1) {
this.isFinished = true;
}
return read;
}
@Override
public boolean isFinished() {
return this.isFinished;
}
@Override
public boolean isReady() {
return true;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public long skip(long n) throws IOException {
return this.is.skip(n);
}
@Override
public int available() throws IOException {
return this.is.available();
}
@Override
public void close() throws IOException {
this.is.close();
}
@Override
public synchronized void mark(int readlimit) {
this.is.mark(readlimit);
}
@Override
public synchronized void reset() throws IOException {
this.is.reset();
}
@Override
public boolean markSupported() {
return this.is.markSupported();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment