You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JSF中如何根据PROJECT_STAGE配置不同错误页面?开发显异常栈,生产显自定义消息

How to Show Different Error Pages Based on JSF PROJECT_STAGE

Absolutely! There are a couple of clean, straightforward ways to implement this requirement in JSF, leveraging the built-in PROJECT_STAGE context parameter and JSF's native error handling tools. Let me break down the most practical approaches for you:

1. Unified Error Page with EL Conditionals (Simplest Approach)

This method uses a single error page that dynamically shows content based on the current PROJECT_STAGE using JSF EL expressions. It’s perfect if you don’t need complex exception processing.

Step 1: Configure Global Error Page in web.xml

First, tell your servlet container to route all unhandled exceptions to a single error page:

<error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/error.xhtml</location>
</error-page>

Step 2: Create the Dynamic Error Page (error.xhtml)

In this page, use #{facesContext.application.projectStage} to check if you’re in Development or Production mode, then render the appropriate content. Servlet containers expose error-related details in the request scope, which you can access to show stack traces in development:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
    <title>Error Occurred</title>
</h:head>
<h:body>
    <!-- Development Environment: Show full exception details -->
    <ui:fragment rendered="#{facesContext.application.projectStage eq 'Development'}">
        <h1>Development Environment Error</h1>
        <div style="margin: 20px 0;">
            <h3>Exception Type:</h3>
            <p>#{requestScope['javax.servlet.error.exception_type']}</p>
        </div>
        <div style="margin: 20px 0;">
            <h3>Exception Message:</h3>
            <p>#{requestScope['javax.servlet.error.message']}</p>
        </div>
        <div style="margin: 20px 0;">
            <h3>Stack Trace:</h3>
            <pre style="background: #f5f5f5; padding: 15px; border-radius: 4px;">#{requestScope['javax.servlet.error.stack_trace']}</pre>
        </div>
        <div style="margin: 20px 0;">
            <h3>Request URI:</h3>
            <p>#{requestScope['javax.servlet.error.request_uri']}</p>
        </div>
    </ui:fragment>

    <!-- Production Environment: Show user-friendly message -->
    <ui:fragment rendered="#{facesContext.application.projectStage eq 'Production'}">
        <h1>Oops! Something Went Wrong</h1>
        <p style="font-size: 1.1em; margin: 20px 0;">
            We’re sorry, but an unexpected issue has occurred. Our team has been notified and is working to fix it right away.
        </p>
        <p style="font-size: 1.1em;">
            Please try again later, or contact our support team if the problem persists.
        </p>
    </ui:fragment>
</h:body>
</html>

2. Custom Exception Handler (Advanced, Flexible Control)

If you need more control—like logging exceptions in production, redirecting to separate error pages, or handling specific exception types differently—use a custom ExceptionHandler.

Step 1: Create the Exception Handler Wrapper

This class checks the PROJECT_STAGE and handles exceptions accordingly:

import javax.faces.application.ProjectStage;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import java.util.Iterator;

public class StageAwareExceptionHandler extends ExceptionHandlerWrapper {

    private final ExceptionHandler wrapped;

    public StageAwareExceptionHandler(ExceptionHandler wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public ExceptionHandler getWrapped() {
        return wrapped;
    }

    @Override
    public void handle() {
        FacesContext context = FacesContext.getCurrentInstance();
        boolean isDevMode = ProjectStage.Development.equals(context.getApplication().getProjectStage());

        Iterator<ExceptionQueuedEvent> exceptionEvents = getUnhandledExceptionQueuedEvents().iterator();
        while (exceptionEvents.hasNext()) {
            ExceptionQueuedEvent event = exceptionEvents.next();
            Throwable exception = event.getContext().getException();

            if (isDevMode) {
                // In dev mode, print stack trace to console (JSF may also show it in the browser)
                exception.printStackTrace();
            } else {
                // In production, log the exception (use your preferred logging framework like SLF4J)
                // Logger.getLogger(getClass()).error("Unhandled exception in production", exception);
                
                // Redirect to a production-specific error page
                try {
                    context.getExternalContext().redirect("/error-production.xhtml");
                    context.renderResponse(); // Signal JSF to skip rendering the original view
                } catch (Exception e) {
                    // Fallback if redirect fails
                    e.printStackTrace();
                }
            }

            exceptionEvents.remove();
        }

        // Let the default handler process any remaining exceptions
        getWrapped().handle();
    }
}

Step 2: Create an Exception Handler Factory

Register your custom handler with JSF using a factory:

import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;

public class CustomExceptionHandlerFactory extends ExceptionHandlerFactory {

    private final ExceptionHandlerFactory parentFactory;

    public CustomExceptionHandlerFactory(ExceptionHandlerFactory parentFactory) {
        this.parentFactory = parentFactory;
    }

    @Override
    public ExceptionHandler getExceptionHandler() {
        return new StageAwareExceptionHandler(parentFactory.getExceptionHandler());
    }
}

Step 3: Configure the Factory in faces-config.xml

Add this entry to register your custom exception handling:

<factory>
    <exception-handler-factory>com.yourpackage.CustomExceptionHandlerFactory</exception-handler-factory>
</factory>

Key Notes

  • Ensure your web.xml has the correct PROJECT_STAGE context parameter—JSF automatically detects this value and makes it available via facesContext.application.projectStage.
  • In development mode, JSF’s default behavior already shows detailed errors, but using a custom error page lets you format the output to your liking.
  • Always avoid exposing sensitive exception details (like stack traces) in production—both methods above ensure this is handled properly.

内容的提问来源于stack exchange,提问作者Nitin Kolte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 15:09:05