我为JSF编写了一个自定义异常处理程序来记录异常并导航到一个错误页面以显示给用户。 不幸的是,我得到了一个IllegalStateException“在提交响应之后无法调用sendRedirect()”在Handler中调用“handleNavigation”时。 任何想法,我做错了什么? ...
提示:本站收集StackOverFlow近2千万问答,支持中英文搜索,鼠标放在语句上弹窗显示对应的参考中文或英文, 本站还提供 中文繁体 英文版本 中英对照 版本,有任何建议请联系yoyou2525@163.com。
我正在努力完全理解在JSF 2.0中何时/如何引发异常。 我寻找解决方案的时间超出了我的意愿。 最终,我要实现的目标是“处理”未处理的异常。 引发异常时,我希望能够捕获有关该异常的感兴趣信息,并将其通过电子邮件发送给适当的站点管理员。 我通过在一个后备bean的构造函数中抛出新的FacesException()来强制执行错误。 在使用MyFaces实现的JSF 1.1中,我的工作非常出色。 我可以通过包装默认生命周期并简单地覆盖execute()和render()方法来使其工作。 我跟随Hanspeter撰写的精彩文章来使该工作正常进行:
“http://insights2jsf.wordpress.com/2009/07/20/using-a-custom-lifecycle-implementation-to-handle-exceptions-in-jsf-1-2/#comment-103”
我现在正在使用Mojarra的网站进行站点升级到JSF 2.0。 但是,只要在execute()方法中引发/捕获了异常,事情就仍然可以正常工作。 当我输入render()时,HttpServletResponse.isCommitted()等于true,阶段是PhaseId RENDER_RESPONSE,这当然意味着我无法执行重定向或转发。 我不知道在JSF 1.1和2.0之间在何时/如何提交响应方面发生了什么变化。 正如我指出的那样,我在1.1框架中可以完美地工作。 经过大量搜索后,我发现JSF 2.0通过Custom ExceptionHandler为异常处理提供了一个很好的选择。 我关注了Ed Burns的博客,在JSF2中优雅地处理ViewExpiredException:
“http://weblogs.java.net/blog/edburns/archive/2009/09/03/dealing-gracefully-viewexpiredexception-jsf2”
正如Ed所指出的,总是通过定义标签以及哪种类型的异常/服务器错误代码以及该错误要发送到的页面始终是web.xml方式。 只要我捕获404错误,此方法就可以很好地工作。 关于这一点,需要注意的一件有趣的事是,如果我通过输入不存在的URL(例如/ myApp / 9er)来强制404错误,则错误处理程序会很好用,但是只要我添加“ .xhtml”扩展名(即/ myApp / 9er.xhtml),那么web.xml定义将无法处理它。
我注意到Ed所做的一件事是我没有尝试过,而不是尝试执行HttpServletRespone.sendRedirect(),而是利用Navigationhandler.handleNavigation()将用户转发到自定义错误页面。 不幸的是,默认情况下,此方法与Faclets所做的操作没有什么不同。 当然,由于上述相同的问题,我无法执行HttpServletResponse.sendRedirect()。 response.isCommitted()等于true。
我知道这篇文章已经很长了,所以我将简要介绍一下出于相同目的尝试使用PhaseListener的情况。 我使用以下帖子作为指导,但此路线仍未成功:
“ http://ovaraksin.blogspot.com/2010/10/global-handling-of-all-unchecked.html”“ http://ovaraksin.blogspot.com/2010/10/jsf-ajax-redirect-after-会话timeout.html”
所有人和我都遇到了与上述相同的问题。 引发此异常时,响应已经处于提交阶段,并且我无法将用户重定向/转发到标准错误页面。
对于这么长的帖子,我深表歉意,我只是想提供尽可能多的信息,以帮助消除歧义。 任何人都有解决问题的想法/想法,我很好奇JSF 1.1和2.0之间可能会有什么不同,一旦我进入生命周期的render()阶段,就会导致响应被提交。
非常感谢您对此提供的任何帮助!!!
因此,这个问题实际上不仅仅涉及自定义异常处理程序(JSF 2具有强大的ExceptionHandlerFactory
机制),而是更多关于在响应已提交时向用户显示自定义错误页面的问题。
即使已经将最后一位写入响应中,始终能够重定向用户的一种通用方法是使用HttpServletResponse
包装器,该包装器缓冲正在写入的标头和内容。
这确实带来了不利影响,即用户看不到正在逐步建立的页面。
也许您可以使用此技术仅捕获JSF 2.0似乎所做的非常早的响应提交。 渲染响应一开始,您就发出缓冲的标头,直到现在为止,然后直接写出响应内容。
这样,如果在渲染响应之前发生异常,您仍然可以将用户重定向到自定义错误页面。
我已经如上所述使用响应包装器成功实现了一个过滤器,该过滤器避免了响应的提交,并且即使在呈现页面的中间发生异常,也允许重定向到自定义页面。
响应包装器在StringWriter上设置其自己的内部PrintWriter,该方法由getWriter方法返回,以便对faces输出进行缓冲。 在快乐路径中,过滤器随后将内部StringWriter内容写入实际响应。 在异常情况下,过滤器重定向到错误jsp,该错误写入到(尚未提交的)响应中。
对我来说,避免提交响应的关键是拦截flushBuffer()方法(来自ServletResponse,而不是HttpServletResponse),并避免调用super.flushBuffer()。 我怀疑,视情况而定,如上所述,可能还需要重写其他一些方法,例如设置标头的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.