【发布时间】:2016-02-25 10:33:37
【问题描述】:
有没有办法在过滤器中读取您的请求正文而不会破坏您的控制器?
即:
- 可以使用
@RequestParam或getParameter(String name)方法获取参数 - 即使您已经在过滤器中需要它,也可以在控制器中获取请求的 InputStream。
【问题讨论】:
标签: servlets servlet-filters query-parameters
有没有办法在过滤器中读取您的请求正文而不会破坏您的控制器?
即:
@RequestParam 或getParameter(String name) 方法获取参数
【问题讨论】:
标签: servlets servlet-filters query-parameters
我的灵感来自这篇文章:Get the POST request body from HttpServletRequest:
它复制然后缓存正文,然后提取参数映射并将其存储在属性formParameters中。
public class MultiReadHttpServletRequest extends HttpServletRequestWrapper {
private final FormHttpMessageConverter formConverter = new AllEncompassingFormHttpMessageConverter();
MultiValueMap<String, String> formParameters;
private ByteArrayOutputStream cachedBytes;
public MultiReadHttpServletRequest(HttpServletRequest request) throws IOException {
super(request);
HttpInputMessage inputMessage = new ServletServerHttpRequest(this) {
@Override
public InputStream getBody() throws IOException {
return getInputStream();
}
};
formParameters = formConverter.read(null, inputMessage);
}
@Override
public ServletInputStream getInputStream() throws IOException {
if (cachedBytes == null)
cacheInputStream();
return new CachedServletInputStream();
}
@Override
public BufferedReader getReader() throws IOException{
return new BufferedReader(new InputStreamReader(getInputStream()));
}
@Override
public String getParameter(String name) {
String queryStringValue = super.getParameter(name);
String formValue = this.formParameters.getFirst(name);
return (queryStringValue != null) ? queryStringValue : formValue;
}
@Override
public Map<String, String[]> getParameterMap() {
Map<String, String[]> result = new LinkedHashMap<>();
Enumeration<String> names = this.getParameterNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
result.put(name, this.getParameterValues(name));
}
return result;
}
@Override
public Enumeration<String> getParameterNames() {
Set<String> names = new LinkedHashSet<>();
names.addAll(Collections.list(super.getParameterNames()));
names.addAll(this.formParameters.keySet());
return Collections.enumeration(names);
}
@Override
public String[] getParameterValues(String name) {
String[] queryStringValues = super.getParameterValues(name);
List<String> formValues = this.formParameters.get(name);
if (formValues == null) {
return queryStringValues;
}
else if (queryStringValues == null) {
return formValues.toArray(new String[formValues.size()]);
}
else {
List<String> result = new ArrayList<>();
result.addAll(Arrays.asList(queryStringValues));
result.addAll(formValues);
return result.toArray(new String[result.size()]);
}
}
private void cacheInputStream() throws IOException {
/* Cache the inputstream in order to read it multiple times. For
* convenience, I use apache.commons IOUtils
*/
cachedBytes = new ByteArrayOutputStream();
IOUtils.copy(super.getInputStream(), cachedBytes);
}
/* An inputstream which reads the cached request body */
public class CachedServletInputStream extends ServletInputStream {
private ByteArrayInputStream input;
public CachedServletInputStream() {
/* create a new input stream from the cached request body */
input = new ByteArrayInputStream(cachedBytes.toByteArray());
}
@Override
public int read() throws IOException {
return input.read();
}
}
}
【讨论】:
cachedBytes 可能很大。
IOUtils.copy(super.getInputStream(), cachedBytes); 移动此对象?