Exception JSF2.0自定义异常处理程序

Exception JSF2.0自定义异常处理程序,exception,jsf-2,handler,Exception,Jsf 2,Handler,我很难完全理解JSF2.0中何时/如何抛出异常。我寻找解决办法的时间比我愿意承认的要长。最终,我想要实现的目标是“处理”未处理的异常。当抛出异常时,我希望能够捕获有关异常的感兴趣的信息,并通过电子邮件将其发送给相应的站点管理员。我通过在我的一个支持bean的构造函数中抛出一个新的FacesException()来强制执行一个错误。我在JSF1.1中使用MyFaces实现实现了这一点。我可以通过包装默认生命周期并简单地重写execute()和render()方法来实现这一点。我跟随Hanspete

我很难完全理解JSF2.0中何时/如何抛出异常。我寻找解决办法的时间比我愿意承认的要长。最终,我想要实现的目标是“处理”未处理的异常。当抛出异常时,我希望能够捕获有关异常的感兴趣的信息,并通过电子邮件将其发送给相应的站点管理员。我通过在我的一个支持bean的构造函数中抛出一个新的FacesException()来强制执行一个错误。我在JSF1.1中使用MyFaces实现实现了这一点。我可以通过包装默认生命周期并简单地重写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的网站升级到JSF2.0。但是,只要在execute()方法中抛出/捕获异常,事情就仍然很顺利;当我输入render()时,HttpServletResponse.isCommitted()等于true,阶段为PhaseId render_RESPONSE,这当然意味着我无法执行重定向或转发。我不明白JSF1.1和2.0之间在响应提交的时间/方式方面发生了什么变化。正如我所指出的,我已经在1.1框架中完美地实现了这一点。 经过多次搜索,我发现JSF2.0通过定制的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.HandlenNavigation()将用户转发到自定义错误页面。不幸的是,此方法与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-session-timeout.html"

我所有的问题都和前面提到的一样。当抛出此异常时,响应已经处于提交阶段,并且我无法将用户重定向/转发到标准错误页面

我为这么长的帖子道歉,我只是想提供尽可能多的信息来帮助消除歧义。任何人对解决方案都有任何想法/想法,我很好奇JSF1.1和2.0之间会有什么不同,在我进入生命周期的render()阶段时会立即提交响应


非常感谢你在这方面的帮助

因此,这个问题实际上不仅仅是关于自定义异常处理程序(JSF2具有强大的
ExceptionHandlerFactory
机制),而是关于在响应已经提交时向用户显示自定义错误页面

即使最后一位已经写入响应,也始终能够重定向用户的一种通用方法是使用缓冲头和写入内容的
HttpServletResponse
包装器

这确实会产生负面影响,用户看不到页面正在逐渐构建

也许您可以使用此技术仅捕获JSF2.0似乎所做的非常早期的响应提交。渲染响应一开始,就发出缓冲到目前为止的标题,并直接写出响应内容


< P>这样,如果在呈现响应之前发生异常,您仍然可以将用户重定向到自定义错误页。

< P>我已经成功地使用响应包装器实现了一个过滤器,如上所述,它避免了响应被提交,并且允许在一个异常页面中间重定向到一个自定义页面。页面

响应包装器在StringWriter上设置自己的内部PrintWriter,它由getWriter方法返回,以便缓冲faces输出。在愉快路径中,过滤器随后将内部StringWriter内容写入实际响应。在异常情况下,过滤器重定向到错误jsp,该错误jsp将写入(尚未提交的)响应


对我来说,避免响应被提交的关键是拦截flushBuffer()方法(来自ServletResponse,而不是HttpServletResponse),并避免调用super.flushBuffer()。我怀疑,根据具体情况和如上所述,可能还需要覆盖其他一些方法,例如设置标题的方法。

非常感谢您的回复!听起来很有趣,我如何让Faces使用我的HttpServletResponseWrapper实现?我将采取哪些步骤来实现它?对于响应包装器,只需使用包含以下内容的doFilter方法创建一个标准servlet过滤器:chain.doFilter(requ