在Handler中进行请求转发后报错,如何解决?

设置一个全局的Handler,对所有的图片资源请求拦截,被拦截到的请求都输出一张特定的图片。

request.getRequestDispatcher("/images/pic.png").forward(request, response);

然后就报错了,貌似是response了两次导致的,但是不知道怎么解决。求指教。

2016-10-12 14:02:08.026:WARN:oejs.ServletHandler:/uploadPic/88cd1af890ec4b379b3f236e3fa5839a.png
java.lang.IllegalStateException: Committed
	at org.eclipse.jetty.server.Response.resetBuffer(Response.java:1136)
	at org.eclipse.jetty.server.Response.reset(Response.java:1057)
	at org.eclipse.jetty.server.Response.reset(Response.java:1108)
	at org.eclipse.jetty.servlet.DefaultServlet.passConditionalHeaders(DefaultServlet.java:688)
	at org.eclipse.jetty.servlet.DefaultServlet.doGet(DefaultServlet.java:504)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:735)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1336)
	at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:82)
	at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1307)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:453)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:560)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1072)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:382)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1006)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
	at org.eclipse.jetty.server.Server.handle(Server.java:365)
	at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:485)
	at org.eclipse.jetty.server.AbstractHttpConnection.headerComplete(AbstractHttpConnection.java:926)
	at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.headerComplete(AbstractHttpConnection.java:988)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:635)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:235)
	at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:628)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
	at java.lang.Thread.run(Thread.java:619)


评论区

JFinal

2016-10-12 15:33

在 Handler 中首先,你要决定是不是要将这个请求传递下去,注意以下几点:
1:当你不去调用 next.handle(...) 时,该请求不会传递给 jfinal 的 ActionHandler
2:当你设置 isHandle[0] = true 后,该请求不会传递给 tomcat、jetty
3:即便是向下传递下去了,接手的组件也会根据情况决定是否自己要处理,例如 ActionHandler 只处理动态请求,对于 /img/abc.jpg 这样的图片请求不会处理,会再转手给 tomcat、jetty
4:这一路下来,不能多次调用 response.getWriter() 并将其关闭

所以,问题原因就很显然了,你自己的代码中有一个 req.getDispatcher(...).forward(...) 已经操作过 writer 关闭,但后续仍然让这个请求继续转手给了 jfinal 或者 jetty/tomcat,而后面接手的组件以为自己还需要处理这个请求,造成重复处理,出异常

JFinal

2016-10-12 15:34

解决方法不需要多说了吧,简单说就是自己处理了,就不要再往下转手了

nbjgl

2016-10-12 15:44

怎么才可以不转手了呀?我试了在请求转发后面加个 return; 但是没效果……

JFinal

2016-10-12 16:04

@nbjgl 前面不是说得很清楚了,避免调用 next.handle(...) 那么 jfinal 后续的组件就不会接手,使用 isHandled[0] = true; 那么 jetty/tomcat 就不会接手,你确定这两项你都做了?

nbjgl

2016-10-12 19:04

原来就差 isHandled[0] = true; 这句啊~ 我把return;删了 , 改成了isHandled[0] = true; 就好了……真是太神奇了,原来这样来禁止jetty接手的啊。

JFinal

2016-10-12 19:08

@nbjgl 建议标题改为 jfinal handler 的使用方法

nbjgl

2016-10-12 19:26

@JFinal 我写了个分享~

热门反馈

扫码入社