大部分的java.lang.IllegalStateException: Cannot forward after response has been committed
异常都是由于response对象在执行完一次向客户端的写操作后,
response.iscommt()==true
再执行一次写操作就会报这个异常.
我这次是在使用nutz时遇到的,
其实在其他环境遇到也一样能解决,
版本是1.b.37-rc.jar
-------------------------------异常栈
java.lang.IllegalStateException: Cannot forward after response has been committed
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:312)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
at org.nutz.mvc.view.ForwardView.render(ForwardView.java:64)
at org.nutz.mvc.impl.processor.ViewProcessor.process(ViewProcessor.java:35)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.MethodInvokeProcessor.process(MethodInvokeProcessor.java:23)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.AdaptorProcessor.process(AdaptorProcessor.java:33)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ActionFiltersProcessor.process(ActionFiltersProcessor.java:42)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.ModuleProcessor.process(ModuleProcessor.java:76)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.EncodingProcessor.process(EncodingProcessor.java:27)
at org.nutz.mvc.impl.processor.AbstractProcessor.doNext(AbstractProcessor.java:44)
at org.nutz.mvc.impl.processor.UpdateRequestAttributesProcessor.process(UpdateRequestAttributesProcessor.java:15)
at org.nutz.mvc.impl.NutActionChain.doChain(NutActionChain.java:36)
at org.nutz.mvc.impl.ActionInvoker.invoke(ActionInvoker.java:66)
at org.nutz.mvc.ActionHandler.handle(ActionHandler.java:30)
at org.nutz.mvc.NutFilter.doFilter(NutFilter.java:66)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at cn.com.fanna.managercontroller.web.filter.XFilter.doFilter(XFilter.java:26)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Unknown Source)
log4j: 2011-06-17 15:43:46,671 [http-8080-2] DEBUG org.nutz.mvc.impl.UrlMappingImpl - find mapping [null] for path [/img]
-----------------------------------------------------
关键是在调用org.nutz.mvc.impl.processor.*processor的doNext()方法时,
调用了iscommit()为true的response对象造成的,
我们只要在这以环节,
判断下iscommt(),
如==true,什么都不干返回,
否则,进行下个next.process()
org.nutz.mvc.impl.processo.
AbstractProcessor.java
是关键,它是其他processors的超类,
所有就改它就可以了
代码:
关键代码:
/**
* 继续执行下一个Processor
* <p/><b>一般情形下都不应该覆盖这个方法<b>
* @param ac 执行方法的上下文
* @throws Throwable
*/
protected void doNext(ActionContext ac) throws Throwable {
if(ac!=null&&ac.getResponse()!=null&&(!ac.getResponse().isCommitted())){ //就加这个判断就好了
if (null != next)
next.process(ac);
}
}
全部代码:
好了,将这个类单独编译出来,放到nutz的jar包中去,就可以了.
-------------------------------------------------------------------
Thinking:
之后问了nutz的作者兽哥,它说就不该让doNext有机会执行,
再次查看异常栈,
发现直接可以在
NutFilter.java做文章,
也就是nutz的启动类,
手段是一样的,
在
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain){}
方法中判断resp的isCommit()状态,做相应修改,应该是这个样子吧
ok ,这样一来,如果response被提交,直接让容器执行其它filter,
离开nutz的范围,与nutz无关了.
还是要感谢nutz的所有贡献者,让我学到了这个有趣的东西,
尤其是兽哥,每天在qq群里解答大家的各种疑问,
再次膜拜下你们.