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

Page tree

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

Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Current »

接口作用

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

接口内容

ErrorHandler
package com.fr.stable.fun;

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

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

    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