JSF ajax 请求中的异常处理

Posted

技术标签:

【中文标题】JSF ajax 请求中的异常处理【英文标题】:Exception handling in JSF ajax requests 【发布时间】:2022-01-07 01:42:19 【问题描述】:

在处理 JSF ajax 请求时抛出异常时,如何处理异常并访问堆栈跟踪?现在,当 JSF 项目阶段设置为 Development 时,我只在 javascript 警报中获得异常类名称和消息。更糟糕的是,当 JSF 项目阶段设置为生产时,没有任何视觉反馈,并且服务器日志没有显示有关异常的任何信息。

如果相关,我在 Netbeans 中使用 GlassFish。

【问题讨论】:

您想在异步请求期间在网页上显示完整的异常堆栈跟踪吗? 没有。我在页面上有一个 按下(使用 ajax 处理)会导致异常。 (i.imgur.com/PdgQvP9.png) 但 Netbeans 中的 Glassfish 输出不显示堆栈跟踪。 (i.imgur.com/a7jqUVz.png)。另一方面,如果是普通的 http 请求,堆栈跟踪将显示在 html 输出 (i.imgur.com/EgxHSP4.png) 中,Netbeans 中的 Glassfish 服务器输出显示堆栈跟踪 (i.imgur.com/6izzfPs.png)。继续…… cont... 当 ajax 请求期间发生错误时,我希望堆栈跟踪显示在 Netbeans 的 Glassfish 输出中(如下所示:i.imgur.com/6izzfPs.png)。 @小小 【参考方案1】:

这个问题在OmniFaces FullAjaxExceptionHandler showcase 中是已知的并得到了充实。

默认情况下,当 JSF ajax 请求期间发生异常时,无论操作是否成功执行,最终用户都不会得到任何形式的反馈。在 Mojarra 中,只有当项目阶段设置为 Development 时,最终用户才会看到仅包含异常类型和消息的纯 JavaScript 警报。

技术原因是异步请求(阅读:Ajax 请求)默认不返回同步响应(阅读:整页)。相反,它们返回小指令和部分如何更新已打开页面的 HTML DOM 树。当异常发生时,那么这些指令基本上是完全不存在的。相反,会发回一些错误信息。您通常可以在 Ajax 组件的 onerror 属性中处理它们,例如显示警报或执行window.location 更改。至少,这是 JSF 对您的期望。

为了捕获和记录异常并选择性地更改整个响应,您基本上需要创建一个自定义ExceptionHandler。不幸的是,标准 JSF 没有提供默认的开箱即用(至少,不是一个明智的)。在您的自定义异常处理程序中,您将能够处理导致所有问题的 Exception 实例。

这是一个启动示例:

public class YourExceptionHandler extends ExceptionHandlerWrapper 

    private ExceptionHandler wrapped;

    public YourExceptionHandler(ExceptionHandler wrapped) 
        this.wrapped = wrapped;
    

    @Override
    public void handle() throws FacesException 
        FacesContext facesContext = FacesContext.getCurrentInstance();

        for (Iterator<ExceptionQueuedEvent> iter = getUnhandledExceptionQueuedEvents().iterator(); iter.hasNext();) 
            Throwable exception = iter.next().getContext().getException(); // There it is!

            // Now do your thing with it. This example implementation merely prints the stack trace.
            exception.printStackTrace();

            // You could redirect to an error page (bad practice).
            // Or you could render a full error page (as OmniFaces does).
            // Or you could show a FATAL faces message.
            // Or you could trigger an oncomplete script.
            // etc..
        

        getWrapped().handle();
    

    @Override
    public ExceptionHandler getWrapped() 
        return wrapped;
    


为了让它运行,创建一个自定义ExceptionHandlerFactory,如下所示:

public class YourExceptionHandlerFactory extends ExceptionHandlerFactory 

    private ExceptionHandlerFactory parent;

    public YourExceptionHandlerFactory(ExceptionHandlerFactory parent) 
        this.parent = parent;
    

    @Override
    public ExceptionHandler getExceptionHandler() 
        return new YourExceptionHandler(parent.getExceptionHandler());
    


需要在faces-config.xml注册如下:

<factory>
    <exception-handler-factory>com.example.YourExceptionHandlerFactory</exception-handler-factory>
</factory>

或者,您可以继续使用 OmniFaces 之一。它将完全透明地确保异步请求期间的异常与同步请求期间的异常行为相同,使用web.xml 中的&lt;error-page&gt; 配置。

另见:

Why FullAjaxExceptionHandler does not simply perform an ExternalContext#redirect()? Authorization redirect on session expiration does not work on submitting a JSF form, page stays the same

【讨论】:

以上是关于JSF ajax 请求中的异常处理的主要内容,如果未能解决你的问题,请参考以下文章

统一处理jquery ajax请求过程中的异常错误信息的机制

JSF 1.x 通用异常处理

jsf中的异常处理 - 在新页面中打印错误消息

前端如何尽量正确地处理ajax的异常?

Ajax--请求超时与网络异常处理

JQuery $.ajax 捕获异常信息