【仅供内部供应商使用,不提供对外解答和培训】

Page tree

【仅供内部供应商使用,不提供对外解答和培训】

Skip to end of metadata
Go to start of metadata

接口作用

提供一个不同于内置报错页面的设置。

接口内容

ErrorHandler
package com.fr.stable.fun;

import com.fr.stable.fun.mark.Immutable;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 错误信息输出器
 */
public interface ErrorHandler extends Immutable {

    String MARK_STRING = "ErrorHandler";

    int CURRENT_LEVEL = 1;

    /**
     * 输出报表服务器在运行时出现的错误信息
     *
     * @param req       HTTP请求
     * @param res       HTTP响应
     * @param throwable 异常
     */
    void error(HttpServletRequest req, HttpServletResponse res, Throwable throwable);

    /**
     * 输出报表服务器在运行时出现的错误信息
     *
     * @param req     HTTP请求
     * @param res     HTTP响应
     * @param message 表示异常信息的字符串
     */
    void error(HttpServletRequest req, HttpServletResponse res, String message);
}

默认实现

DefaultErrorHandler
package com.fr.web.core;

import com.fr.base.ConfigManager;
import com.fr.base.Env;
import com.fr.base.FRContext;
import com.fr.base.TemplateUtils;
import com.fr.json.JSONException;
import com.fr.json.JSONObject;
import com.fr.stable.CodeUtils;
import com.fr.stable.ProductConstants;
import com.fr.stable.StableUtils;
import com.fr.stable.StringUtils;
import com.fr.stable.fun.ErrorHandler;
import com.fr.stable.fun.impl.AbstractErrorHandler;
import com.fr.web.utils.WebUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 默认的向页面输出报错信息的错误输出器
 */
public class DefaultErrorHandler extends AbstractErrorHandler {
    /**
     * 默认的构造函数
     */
    public DefaultErrorHandler() {
    }

    /**
     * 输出报表服务器在运行时出现的错误信息
     *
     * @param req       HTTP请求
     * @param res       HTTP响应
     * @param throwable 异常
     */
    public void error(HttpServletRequest req, HttpServletResponse res, Throwable throwable) {
        error(req, res, throwable.getMessage(), throwable);
    }

    /**
     * 输出报表服务器在运行时出现的错误信息
     *
     * @param req     HTTP请求
     * @param res     HTTP响应
     * @param message 表示异常信息的字符串
     */
    public void error(HttpServletRequest req, HttpServletResponse res, String message) {
        error(req, res, message, null);
    }

    /**
     * 输出报表服务器在运行时出现的错误信息
     *
     * @param req       HTTP请求
     * @param res       HTTP响应
     * @param message   表示异常信息的字符串
     * @param throwable 异常
     */
    public void error(HttpServletRequest req, HttpServletResponse res,
                      String message, Throwable throwable) {
        if (WebUtils.getDevice(req).isMobile()) {
            postErrorMessageWithJSONObject(req, res, message, throwable);
        } else {
            postErrorMessageOnPC(req, res, message, throwable);
        }
    }

    private void postErrorMessageOnPC(HttpServletRequest req, HttpServletResponse res, String message, Throwable throwable) {
        Map<String, Object> map = new HashMap<String, Object>();
        if (message == null) {//保证message不能为null.
            message = StringUtils.EMPTY;
        }
        map.put("message", CodeUtils.htmlEncode(CodeUtils.cjkEncode(message)));
        map.put("duration", ProductConstants.HISTORY);
        map.put("companyname", ProductConstants.COMPANY_NAME);
        try {
            if (req.getParameter("frload") != null) {
                //说明是在loading.js访问时出现的问题,那么不能传html文件过去,应该传一个alert的东西过去
                PrintWriter writer = WebUtils.createPrintWriter(res);
                writer.println(new StringBuffer().append("alert(\"").append(message.replaceAll("\"", "\\\\\"")).append("\")"));
                writer.flush();
                writer.close();
                return;
            }

            if (throwable != null) {
                map.put("exception", createThrowableMessage(throwable, true));
            }
            //james:error页面的编码从FRContext中获取
            map.put("charset", CodeUtils.htmlEncode(ConfigManager.getProviderInstance().getServerCharset()));

            String errorTemplate = "/com/fr/web/core/errorIframe.html";

            // 自定义出错页面
            if (StringUtils.isNotEmpty(ConfigManager.getProviderInstance().getErrorTemplate())) {
                try {
                    userDefineHandler(req, res, map);
                } catch (Exception e) {
                    WebUtils.writeOutTemplate(errorTemplate, res, map);
                    FRContext.getLogger().error(e.getMessage());
                }
            } else {
                WebUtils.writeOutTemplate(errorTemplate, res, map);
            }
        } catch (IOException ioe) {
            FRContext.getLogger().errorWithServerLevel(ioe.getMessage(), ioe);
        }
    }

    private void postErrorMessageWithJSONObject(HttpServletRequest req, HttpServletResponse res, String message, Throwable throwable) {
        JSONObject errorJSON = new JSONObject();
        PrintWriter writer = null;
        try {
            errorJSON.put("message", message);
            errorJSON.put("exception", createThrowableMessage(throwable, false));
            writer = WebUtils.createPrintWriter(res);
            writer.println(errorJSON);
            writer.flush();
            writer.close();
        } catch (Exception e) {
            try {
                errorJSON.put("exception", createThrowableMessage(e.getCause(), false));
            } catch (JSONException e1) {
                FRContext.getLogger().error(e.getMessage(), e);
            }
        } finally {
            if (writer != null) {
                writer.flush();
                writer.close();
            }
        }
    }

    private String createThrowableMessage(Throwable throwable, boolean useCJK) {
        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);
        throwable.printStackTrace(printWriter);
        try {
            return useCJK ? CodeUtils.htmlEncode(CodeUtils.cjkEncode(stringWriter.toString())) : stringWriter.toString();
        } finally {
            printWriter.flush();
            printWriter.close();
        }
    }

    private void userDefineHandler(HttpServletRequest req, HttpServletResponse res, Map map) throws Exception {
        Env currentEnv = FRContext.getCurrentEnv();
        if (currentEnv == null) {
            throw new IllegalStateException("Env is null..");
        }

        String errorTemplate = ConfigManager.getProviderInstance().getErrorTemplate();

        if (StringUtils.isNotEmpty(errorTemplate) && !errorTemplate.endsWith(".html")) {
            if (errorTemplate.length() > 0 && errorTemplate.charAt(0) == '/') {
                errorTemplate = req.getContextPath() + errorTemplate;
            }

            map.put("redirectURL", errorTemplate);
            WebUtils.writeOutTemplate("/com/fr/web/core/errorPostRedirect.html", res, map);
        } else {
            String envPath = currentEnv.getPath();
            File htmlFile = new File(StableUtils.pathJoin(new String[]{new File(envPath).getParent(), errorTemplate}));

            PrintWriter printWriter = WebUtils.createPrintWriter(res);
            TemplateUtils.dealWithTemplate(new FileInputStream(htmlFile), StableUtils.RESOURCE_ENCODER, printWriter, map);

            printWriter.flush();
            printWriter.close();
        }
    }
}

注册方式

<extra-core>
   <ErrorHandler class="com.fr.plugin.xxx.youclassname"/>
</extra-core>
  • No labels