Last active
January 18, 2024 06:57
-
-
Save vamdt/8cef782411345969902f4da8ae14866e to your computer and use it in GitHub Desktop.
兼容各种请求格式的重复读HttpServletRequestWrapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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