我可以确认您所看到的行为。我认为在调用 Application.cfc 之前,CF servlet 抛出了异常,这可以解释为什么 onError 永远不会触发。
到目前为止,对我有用的唯一选项是WEB-INF\web.xml 中的adding a custom error page,使用 HTTP 状态代码:
<error-page>
<error-code>400</error-code>
<location>/path/to/myErrorPage.cfm</location>
</error-page>
注意:在 cmets 中,@Adrian 提到他将上述内容添加到 \cfusion\runtime\conf\web.xml,而不是 web-inf\ 中的那个。
更新 1:
进一步阅读表明您还可以在更精细的级别上进行配置。要处理特定的kind of exception,请使用<exception-type> 而不是<error-code>。例如:
<error-page>
<exception-type>java.lang.Exception</exception-type>
<location>/path/to/myErrorPage.cfm</location>
</error-page>
也就是说,在我的(简短)测试中,CF10 似乎使用了非常通用的异常类来解决这个错误。两者都有很多潜在的原因,而不仅仅是张贴了太多的表单字段。所以记住这一点。当然,它比处理所有 HTTP 500 错误更专注,但它也可能包含其他原因。
javax.servlet.ServletException: ROOT CAUSE:
java.lang.IllegalStateException: Cannot call sendError() ..
更新 2:
原来javax.servlet.ServletException 只是一个红鲱鱼。正如@AdrianWright 在 cmets 中指出的那样,该错误与调试设置有关。当 CF 生成“最大数量的 POST 请求参数”消息时,它没有正确考虑调试,进而导致 new 异常:java.lang.IllegalStateException。因此出现 HTTP 500 错误:
当调试被禁用时(就像在生产系统上那样),CF 只是将错误消息直接写入响应流并返回 HTTP 状态代码 400。由于没有抛出异常,<exception-type> 在这里毫无用处。所以你被困在使用状态码:
<error-page>
<error-code>400</error-code>
<location>/path/to/myErrorPage.cfm</location>
</error-page>
但是,在自定义错误页面上,您可以extract the error message from the request stream。然后进行相应处理:
<cfset req = getPageContext().getRequest()>
<cfset message = req.getAttribute("javax.servlet.error.message")>
<cfif message contains "POST parameters exceeds">
Too many form fields. do something...
<cfelse>
Some other cause. do something else
</cfif>