我有以下代码:
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { logger.info("Filter start..."); HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletResponse httpResponse = (HttpServletResponse) response; String ba = getBaId(getBody(httpRequest)); if (ba == null) { logger.error("Wrong XML"); httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST); } else { if (!clients.containsKey(ba)) { clients.put(ba, 1); logger.info("Client map : init..."); } else { clients.put(ba, clients.get(ba).intValue() + 1); logger.info("Threads for " + ba + " = " + clients.get(ba).toString()); } chain.doFilter(request, response); } }
和此web.xml(缩短了程序包并更改了名称,但外观相同)
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app> <filter> <filter-name>TestFilter</filter-name> <filter-class>pkg.TestFilter</filter-class> </filter> <filter-mapping> <filter-name>TestFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>Name</servlet-name> <display-name>Name</display-name> <servlet-class>pkg.Name</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Name</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> </web-app>
我想在过滤器之后调用Servlet。我希望chain.doFilter(...)可以做到这一点,但是我总是会遇到以下错误chain.doFilter(...):
chain.doFilter(...)
java.lang.IllegalStateException: getInputStream() can't be called after getReader() at com.caucho.server.connection.AbstractHttpRequest.getInputStream(AbstractHttpRequest.java:1933) at org.apache.cxf.transport.http.AbstractHTTPDestination.setupMessage(AbstractHTTPDestination.java:249) at org.apache.cxf.transport.servlet.ServletDestination.invoke(ServletDestination.java:82) at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:283) at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:166) at org.apache.cxf.transport.servlet.AbstractCXFServlet.invoke(AbstractCXFServlet.java:174) at org.apache.cxf.transport.servlet.AbstractCXFServlet.doPost(AbstractCXFServlet.java:152) at javax.servlet.http.HttpServlet.service(HttpServlet.java:153) at javax.servlet.http.HttpServlet.service(HttpServlet.java:91) at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:103) at pkg.TestFilter.doFilter(TestFilter.java:102) at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:87) at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:187) at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:265) at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:273) at com.caucho.server.port.TcpConnection.run(TcpConnection.java:682) at com.caucho.util.ThreadPool$Item.runTasks(ThreadPool.java:743) at com.caucho.util.ThreadPool$Item.run(ThreadPool.java:662) at java.lang.Thread.run(Thread.java:619)
你可能开始使用getReader() in 使用HttpServletRequest :
getReader()
String ba = getBaId(getBody(httpRequest));
你的servlet尝试调用getInputStream()相同的请求,这是不允许的。你需要做的是使用ServletRequestWrapper制作请求正文的副本,因此你可以使用多种方法读取它。
getInputStream()
ServletRequestWrapper
基于接受的答案的工作代码。
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper { private static final Logger logger = Logger.getLogger(CustomHttpServletRequestWrapper.class); private final String body; public CustomHttpServletRequestWrapper(HttpServletRequest request) { super(request); StringBuilder stringBuilder = new StringBuilder(); BufferedReader bufferedReader = null; try { InputStream inputStream = request.getInputStream(); if (inputStream != null) { bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); char[] charBuffer = new char[128]; int bytesRead = -1; while ((bytesRead = bufferedReader.read(charBuffer)) > 0) { stringBuilder.append(charBuffer, 0, bytesRead); } } else { stringBuilder.append(""); } } catch (IOException ex) { logger.error("Error reading the request body..."); } finally { if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException ex) { logger.error("Error closing bufferedReader..."); } } } body = stringBuilder.toString(); } @Override public ServletInputStream getInputStream () throws IOException { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes()); ServletInputStream inputStream = new ServletInputStream() { public int read () throws IOException { return byteArrayInputStream.read(); } }; return inputStream; } }