【发布时间】:2011-10-10 11:14:34
【问题描述】:
我在我的应用程序中添加了一个过滤器,它只记录有关请求的某些内容。我的一些 servlet 读取自 ServletRequest#getInputStream。由于添加了这个过滤器,那些从ServletRequest#getInputStream 读取的servlet 不再工作,因为输入流是空的。通过简单地从我的web.xml 中注释掉过滤器来禁用过滤器即可解决问题。
为什么会发生这种情况?有没有办法使用过滤器而不弄乱ServletRequest#getInputStream?
过滤器实际上是 Tomcat 的 RequestDumperFilter,包含在其示例 Web 应用程序之一中。我将只包括doFilter 方法,因为这是重要的部分。如果你想看整个事情,我已经把它放在PasteBin。
/**
* Time the processing that is performed by all subsequent filters in the
* current filter stack, including the ultimately invoked servlet.
*
* @param request The servlet request we are processing
* @param result The servlet response we are creating
* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
if (filterConfig == null)
return;
// Render the generic servlet request properties
StringWriter sw = new StringWriter();
PrintWriter writer = new PrintWriter(sw);
writer.println("Request Received at " +
(new Timestamp(System.currentTimeMillis())));
writer.println(" characterEncoding=" + request.getCharacterEncoding());
writer.println(" contentLength=" + request.getContentLength());
writer.println(" contentType=" + request.getContentType());
writer.println(" locale=" + request.getLocale());
writer.print(" locales=");
Enumeration locales = request.getLocales();
boolean first = true;
while (locales.hasMoreElements()) {
Locale locale = (Locale) locales.nextElement();
if (first)
first = false;
else
writer.print(", ");
writer.print(locale.toString());
}
writer.println();
Enumeration names = request.getParameterNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
writer.print(" parameter=" + name + "=");
String values[] = request.getParameterValues(name);
for (int i = 0; i < values.length; i++) {
if (i > 0)
writer.print(", ");
writer.print(values[i]);
}
writer.println();
}
writer.println(" protocol=" + request.getProtocol());
writer.println(" remoteAddr=" + request.getRemoteAddr());
writer.println(" remoteHost=" + request.getRemoteHost());
writer.println(" scheme=" + request.getScheme());
writer.println(" serverName=" + request.getServerName());
writer.println(" serverPort=" + request.getServerPort());
writer.println(" isSecure=" + request.isSecure());
// Render the HTTP servlet request properties
if (request instanceof HttpServletRequest) {
writer.println("---------------------------------------------");
HttpServletRequest hrequest = (HttpServletRequest) request;
writer.println(" contextPath=" + hrequest.getContextPath());
Cookie cookies[] = hrequest.getCookies();
if (cookies == null)
cookies = new Cookie[0];
for (int i = 0; i < cookies.length; i++) {
writer.println(" cookie=" + cookies[i].getName() +
"=" + cookies[i].getValue());
}
names = hrequest.getHeaderNames();
while (names.hasMoreElements()) {
String name = (String) names.nextElement();
String value = hrequest.getHeader(name);
writer.println(" header=" + name + "=" + value);
}
writer.println(" method=" + hrequest.getMethod());
writer.println(" pathInfo=" + hrequest.getPathInfo());
writer.println(" queryString=" + hrequest.getQueryString());
writer.println(" remoteUser=" + hrequest.getRemoteUser());
writer.println("requestedSessionId=" +
hrequest.getRequestedSessionId());
writer.println(" requestURI=" + hrequest.getRequestURI());
writer.println(" servletPath=" + hrequest.getServletPath());
}
writer.println("=============================================");
// Log the resulting string
writer.flush();
filterConfig.getServletContext().log(sw.getBuffer().toString());
// Pass control on to the next filter
chain.doFilter(request, response);
}
结论
根据我从Googling 阅读的内容,如果首先调用,以下任何方法都会使getInputStream 为空:
getParametergetParameterNamesgetParameterValuesgetParameterMap
感谢 SimoneGianni 为我指明了正确的方向:
这里有一些来源
- http://www.xyzws.com/Servletfaq/what-is-the-getinputstream-of-servletrequest-for/23
- http://davidhuo.blogspot.com/2006/05/be-careful-with-httpservletrequestgeti.html
- https://issues.apache.org/bugzilla/show_bug.cgi?id=47410
这个人实际上遇到了类似的问题,并创建了自己的包装类作为解决方法。
【问题讨论】:
-
可以加一些过滤代码吗?
-
当然。它实际上是 Tomcat 的 RequestDumperFilter,它包含在其中一个示例 Web 应用程序中。我会在上面的问题中弹出它。
标签: java tomcat6 inputstream servlet-filters