由freemarker切换到enjoy之后,项目启动,必然报这个错误

03-30 14:15:56.927:ERROR(ActionHandler.java:113)-/
com.jfinal.render.RenderException: java.lang.RuntimeException: org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
	at com.jfinal.render.TemplateRender.render(TemplateRender.java:62)
	at com.jfinal.core.ActionHandler.handle(ActionHandler.java:108)
	at com.jfinal.plugin.druid.DruidStatViewHandler.handle(DruidStatViewHandler.java:81)
	at com.jfinal.ext.handler.UrlSkipHandler.handle(UrlSkipHandler.java:46)
	at com.jfinal.ext.handler.ContextPathHandler.handle(ContextPathHandler.java:48)
	at com.ibdyr.system.i18n.I18nHandler.handle(I18nHandler.java:40)
	at com.jfinal.core.JFinalFilter.doFilter(JFinalFilter.java:73)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:651)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:417)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:754)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1376)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.RuntimeException: org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
	at com.jfinal.template.io.ByteWriter.close(ByteWriter.java:54)
	at com.jfinal.template.Template.render(Template.java:57)
	at com.jfinal.render.TemplateRender.render(TemplateRender.java:60)
	... 25 more
Caused by: org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
	at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:333)
	at org.apache.catalina.connector.OutputBuffer.flushByteBuffer(OutputBuffer.java:748)
	at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:287)
	at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:261)
	at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:118)
	at com.jfinal.template.io.ByteWriter.close(ByteWriter.java:51)
	... 27 more
Caused by: java.io.IOException: Broken pipe
	at sun.nio.ch.FileDispatcherImpl.write0(Native Method)
	at sun.nio.ch.SocketDispatcher.write(SocketDispatcher.java:47)
	at sun.nio.ch.IOUtil.writeFromNativeBuffer(IOUtil.java:93)
	at sun.nio.ch.IOUtil.write(IOUtil.java:65)
	at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:471)
	at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:134)
	at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101)
	at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:157)
	at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.doWrite(NioEndpoint.java:1184)
	at org.apache.tomcat.util.net.SocketWrapperBase.doWrite(SocketWrapperBase.java:691)
	at org.apache.tomcat.util.net.SocketWrapperBase.writeBlocking(SocketWrapperBase.java:471)
	at org.apache.tomcat.util.net.SocketWrapperBase.write(SocketWrapperBase.java:409)
	at org.apache.coyote.http11.Http11OutputBuffer$SocketOutputBuffer.doWrite(Http11OutputBuffer.java:530)
	at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:110)
	at org.apache.coyote.http11.Http11OutputBuffer.doWrite(Http11OutputBuffer.java:189)
	at org.apache.coyote.Response.doWrite(Response.java:538)
	at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:328)
	... 32 more


评论区

JFinal

2018-03-30 15:34

ClientAbortException 这个异常是指客户端中途断开了连接终止了请求,这个在 jfinal 3.4 已经处理过了

这个问题本可以不用处理,但为了提升用户体验,还是处理了一下,建议先通过这种办法用上 jfinal 3.4:
http://www.jfinal.com/share/714

badouyuren

2018-03-30 15:36

@JFinal 多谢多谢

JFinal

2018-03-30 15:45

@badouyuren 如果暂时不想升级,还可以拿到 jfinal 3.4 中的 TemplateRender.java 这个源代码,改名为 MyTemplateRender.java ,然后通过下面的代码进行切换:
public class MyRenderFactory extends RenderFactory {
public Render getRender(String view) {
render(new MyTemplateRender(view));
}

最后配置一下切换到新的实现:
me.setRenderFactory(new MyRenderFactory());

当然,如果你有 BaseController 的话,还可以在其中添加一个 render(String) 方法来覆盖父类实现:
public void render(String view) {
render(new MyTemplateRender(view));
}

JFinal

2018-03-30 15:46

TemplateRender 源码在这里可以拿到 3.4 版本的:
https://gitee.com/jfinal/jfinal/blob/master/src/main/java/com/jfinal/render/TemplateRender.java

badouyuren

2018-03-30 22:16

@JFinal 多谢您的建议,不过,我看了源码之后,感觉这个只是解决办法只是捕获到这个错误,没有抛出,如您上面说的,这个问题本可以不用处理,为什么不要处理呢?

JFinal

2018-03-31 01:09

@badouyuren 这个异常是无法去避免的客户端的行为,而且在很多情况下属于正常行为,所以不需要处理。

例如客户端点击下载文件,下载到一半时点击取消下载。

再例如某个页面后台处理的时间较长,用户还没等到页面跳转就不等待去点击了别的链接

阿帕奇

2018-06-27 15:47

@JFinal 我替换到了3.4的版本还是报以下异常,当用户在页面狂按F5刷新的时候报这个,其他都正常:
java.lang.RuntimeException: org.apache.catalina.connector.ClientAbortException: java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
at com.jfinal.template.io.ByteWriter.close(ByteWriter.java:54) ~[jfinal-3.4.jar:na]
at com.jfinal.template.Template.render(Template.java:61) ~[jfinal-3.4.jar:na]
at com.jfinal.template.ext.spring.JFinalView.renderMergedTemplateModel(JFinalView.java:60) ~[jfinal-3.4.jar:na]
at org.springframework.web.servlet.view.AbstractTemplateView.renderMergedOutputModel(AbstractTemplateView.java:167) ~[spring-webmvc-4.3.14.RELEASE.jar:na]
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:303) ~[spring-webmvc-4.3.14.RELEASE.jar:na]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1286) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1041) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:984) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[servlet-api.jar:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.14.RELEASE.jar:4.3.14.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[servlet-api.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) [catalina.jar:8.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.24]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-websocket.jar:8.0.24]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.24]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.14.RELEASE.jar:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.14.RELEASE.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.24]
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.14.RELEASE.jar:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.14.RELEASE.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.24]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.14.RELEASE.jar:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.14.RELEASE.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.24]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.14.RELEASE.jar:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.14.RELEASE.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.24]
at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:115) [spring-boot-1.5.10.RELEASE.jar:na]
at org.springframework.boot.web.support.ErrorPageFilter.access$000(ErrorPageFilter.java:59) [spring-boot-1.5.10.RELEASE.jar:na]
at org.springframework.boot.web.support.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:90) [spring-boot-1.5.10.RELEASE.jar:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) [spring-web-4.3.14.RELEASE.jar:na]
at org.springframework.boot.web.support.ErrorPageFilter.doFilter(ErrorPageFilter.java:108) [spring-boot-1.5.10.RELEASE.jar:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) [catalina.jar:8.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) [catalina.jar:8.0.24]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) [catalina.jar:8.0.24]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) [catalina.jar:8.0.24]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) [catalina.jar:8.0.24]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) [catalina.jar:8.0.24]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) [catalina.jar:8.0.24]
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:617) [catalina.jar:8.0.24]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) [catalina.jar:8.0.24]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) [catalina.jar:8.0.24]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) [tomcat-coyote.jar:8.0.24]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668) [tomcat-coyote.jar:8.0.24]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1527) [tomcat-coyote.jar:8.0.24]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1484) [tomcat-coyote.jar:8.0.24]
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_25]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_25]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-util.jar:8.0.24]
at java.lang.Thread.run(Unknown Source) [na:1.8.0_25]
Caused by: org.apache.catalina.connector.ClientAbortException: java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:393) ~[catalina.jar:8.0.24]
at org.apache.tomcat.util.buf.ByteChunk.flushBuffer(ByteChunk.java:426) ~[tomcat-util.jar:8.0.24]
at org.apache.catalina.connector.OutputBuffer.doFlush(OutputBuffer.java:342) ~[catalina.jar:8.0.24]
at org.apache.catalina.connector.OutputBuffer.flush(OutputBuffer.java:317) ~[catalina.jar:8.0.24]
at org.apache.catalina.connector.CoyoteOutputStream.flush(CoyoteOutputStream.java:110) ~[catalina.jar:8.0.24]
at com.jfinal.template.io.ByteWriter.close(ByteWriter.java:51) ~[jfinal-3.4.jar:na]
... 57 common frames omitted
Caused by: java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
at sun.nio.ch.SocketDispatcher.write0(Native Method) ~[na:1.8.0_25]
at sun.nio.ch.SocketDispatcher.write(Unknown Source) ~[na:1.8.0_25]
at sun.nio.ch.IOUtil.writeFromNativeBuffer(Unknown Source) ~[na:1.8.0_25]
at sun.nio.ch.IOUtil.write(Unknown Source) ~[na:1.8.0_25]
at sun.nio.ch.SocketChannelImpl.write(Unknown Source) ~[na:1.8.0_25]
at org.apache.tomcat.util.net.NioChannel.write(NioChannel.java:127) ~[tomcat-coyote.jar:8.0.24]
at org.apache.tomcat.util.net.NioBlockingSelector.write(NioBlockingSelector.java:101) ~[tomcat-coyote.jar:8.0.24]
at org.apache.tomcat.util.net.NioSelectorPool.write(NioSelectorPool.java:173) ~[tomcat-coyote.jar:8.0.24]
at org.apache.coyote.http11.InternalNioOutputBuffer.writeToSocket(InternalNioOutputBuffer.java:139) ~[tomcat-coyote.jar:8.0.24]
at org.apache.coyote.http11.InternalNioOutputBuffer.flushBuffer(InternalNioOutputBuffer.java:244) ~[tomcat-coyote.jar:8.0.24]
at org.apache.coyote.http11.InternalNioOutputBuffer.addToBB(InternalNioOutputBuffer.java:189) ~[tomcat-coyote.jar:8.0.24]
at org.apache.coyote.http11.InternalNioOutputBuffer.access$000(InternalNioOutputBuffer.java:41) ~[tomcat-coyote.jar:8.0.24]
at org.apache.coyote.http11.InternalNioOutputBuffer$SocketOutputBuffer.doWrite(InternalNioOutputBuffer.java:320) ~[tomcat-coyote.jar:8.0.24]
at org.apache.coyote.http11.filters.ChunkedOutputFilter.doWrite(ChunkedOutputFilter.java:116) ~[tomcat-coyote.jar:8.0.24]
at org.apache.coyote.http11.AbstractOutputBuffer.doWrite(AbstractOutputBuffer.java:256) ~[tomcat-coyote.jar:8.0.24]
at org.apache.coyote.Response.doWrite(Response.java:503) ~[tomcat-coyote.jar:8.0.24]
at org.apache.catalina.connector.OutputBuffer.realWriteBytes(OutputBuffer.java:388) ~[catalina.jar:8.0.24]
... 62 common frames omitted

JFinal

2018-06-27 16:03

@阿帕奇 参考一下 TemplateRender 改进一下 JFinalView 里头有关 ClientAbortException 这个异常

JFinal

2018-06-27 23:10

@阿帕奇 突然想起来了,是 tomcat 8 的某个版本的 bug ,升级一下 tomcat

阿帕奇

2018-06-28 09:45

@JFinal 谢谢指导,换了8.5.32还是不得行,换了9.0.10还是不得行;继续研究中....

JFinal

2018-06-28 10:15

@阿帕奇 参考一下 TemplateRender 改进一下 JFinalView 里头有关 ClientAbortException 这个异常

简单来说就是 try catch 这个 ClientAbortException 来解决,try catch 在关代码照抄 TemplateRender.java

阿帕奇

2018-06-29 10:31

@JFinal 感谢波总指点,问题已经解决了;tomcat的版本是一个问题,其中还有一个问题是在报错之前有一句提示我给忽略了:Cannot forward to error page for request [/] as the response has already been committed. As a result, the response may have the wrong status code. If your application is running on WebSphere Application Server you may be able to resolve this problem by setting com.ibm.ws.webcontainer.invokeFlushAfterService to false
只需要在springboot的启动类Application中加入:setRegisterErrorPageFilter(false);就可以了;我的项目是springboot+jfinal+dubbo的架构;

JFinal

2018-06-29 18:08

@阿帕奇 JFinalView 里头有关 ClientAbortException 这个改动过没有? 难道不改这个就解决了?

阿帕奇

2018-07-02 08:43

@JFinal 我没改ClientAbortException 有关信息,也不知道怎么改动;在开发环境还会报错,但是我代码拿到生产环境和测试环境都不报错了;

JFinal

2018-07-02 11:29

@阿帕奇 将 JFinalView 中的下面两行代码:
OutputStream os = response.getOutputStream();
JFinalViewResolver.engine.getTemplate(getUrl()).render(model, os);

外面套上 try catch ,改成:
try {
OutputStream os = response.getOutputStream();
JFinalViewResolver.engine.getTemplate(getUrl()).render(model, os);
} catch (Exception e) { // 捕获 ByteWriter.close() 抛出的 RuntimeException
Throwable cause = e.getCause();
if (cause instanceof IOException) { // ClientAbortException、EofException 直接或间接继承自 IOException
String name = cause.getClass().getSimpleName();
if ("ClientAbortException".equals(name) || "EofException".equals(name)) {
return ;
}
}

throw e;
}


然后使用自己的 JFinalView 代替 jfinal 的 JFinalView 即可