我正在努力完全理解JSF 2.0中何时/如何抛出异常。我寻找的解决方案比我承认的要长。最终,我想要实现的目标是“处理”未处理的异常。抛出异常时,我希望能够捕获有关异常的感兴趣信息,并将其通过电子邮件发送给相应的站点管理员。我通过在我的一个支持bean的构造函数中抛出一个新的FacesException()来强制出错。我使用MyFaces实现在JSF 1.1中使用了这个功能。我能够通过包装Default Lifecycle并简单地覆盖execute()和render()方法来实现这一点。我按照Hanspeter的这篇精彩文章来完成这项工作:
“http://insights2jsf.wordpress.com/2009/07/20/using-a-custom-lifecycle-implementation-to-handle-exceptions-in-jsf-1-2/#comment-103”< / p>
我正在使用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错误,这种方法效果很好。然而,值得注意的一件有趣的事情是,如果我通过键入像/ myApp / 9er这样的非异常URL强制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()阶段后立即提交。
非常感谢你们提供任何帮助!!!
答案 0 :(得分:3)
所以这个问题实际上不仅仅是关于自定义异常处理程序(JSF 2具有强大的ExceptionHandlerFactory
机制),而是关于在响应已经提交时向用户显示自定义错误页面的更多信息。 / p>
即使最后一位已写入响应,也始终能够重定向用户的一种通用方法是使用HttpServletResponse
包装器来缓冲标头和正在写入内容的内容。
这确实会产生不利影响,即用户没有看到页面逐渐建立起来。
也许你可以使用这种技术来捕获JSF 2.0似乎做的早期响应提交。渲染响应一开始,就会发出缓冲到目前为止的标题并直接写出响应内容。
这样,如果在呈现响应之前发生异常,您仍可以将用户重定向到自定义错误页面。
答案 1 :(得分:1)
我已经使用如上所述的响应包装器成功实现了一个过滤器,它避免了响应被提交,并允许重定向到自定义页面,即使在呈现页面的过程中也是如此。
响应包装器在StringWriter上设置自己的内部PrintWriter,它由getWriter方法返回,以便缓冲faces输出。在快乐路径中,过滤器随后将内部StringWriter内容写入实际响应。在异常情况下,过滤器重定向到错误jsp,该错误写入(尚未提交)响应。
对我来说,避免响应被提交的关键是拦截flushBuffer()方法(来自ServletResponse,而不是HttpServletResponse),并避免调用super.flushBuffer()。我怀疑,根据具体情况并如上所述,可能还需要覆盖其他一些方法,例如设置标题的方法。