JEditorPaneHTMLEditorKitParserMethodRuntimeException运行时异常

wen java案例 1

本文目录导读:

JEditorPaneHTMLEditorKitParserMethodRuntimeException运行时异常

  1. 常见原因
  2. 解决方案
  3. 最佳实践建议

遇到 JEditorPane + HTMLEditorKitParserMethodRuntimeException 运行时异常,通常是因为解析 HTML 内容时遇到了不符合规范或无法识别的标签/语法,以下是常见原因和解决方案:

常见原因

  1. HTML 结构不完整(缺少 DOCTYPE/closing tags)
  2. 特殊字符未转义<, >, & 等)
  3. 不支持的 HTML 标签或属性
  4. 编码问题(UTF-8 vs GBK 混淆)
  5. 嵌套层级过深

解决方案

使用更稳定的解析方式

JEditorPane editor = new JEditorPane();
editor.setContentType("text/html");
// 方法1:使用内置HTML编辑器
HTMLEditorKit kit = new HTMLEditorKit();
editor.setEditorKit(kit);
// 方法2:设置自定义Document
HTMLDocument doc = (HTMLDocument) kit.createDefaultDocument();
doc.setAsynchronousLoadPriority(-1); // 同步加载,避免并发问题
editor.setDocument(doc);
try {
    editor.setText("<html><body><p>Safe content</p></body></html>");
} catch (RuntimeException e) {
    // 捕获并处理
    handleParsingError(e);
}

预处理 HTML 内容

public class HTMLSanitizer {
    public static String preprocessHTML(String rawHTML) {
        // 1. 添加基础结构
        if (!rawHTML.toLowerCase().contains("<html>")) {
            rawHTML = "<html><body>" + rawHTML + "</body></html>";
        }
        // 2. 转义特殊字符(只对非标签部分)
        rawHTML = escapeSpecialChars(rawHTML);
        // 3. 移除不支持的标签
        rawHTML = rawHTML.replaceAll("(?i)<(script|style|object|embed)[^>]*>[^<]*</\\1>", "");
        // 4. 修复自闭合标签
        rawHTML = rawHTML.replaceAll("(?i)<(br|hr|img|input|meta|link)([^>]*)>", "<$1$2/>");
        return rawHTML;
    }
    private static String escapeSpecialChars(String html) {
        StringBuilder sb = new StringBuilder();
        boolean inTag = false;
        for (char c : html.toCharArray()) {
            if (c == '<') inTag = true;
            else if (c == '>') inTag = false;
            if (!inTag && c == '&') {
                sb.append("&amp;");
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }
}

异常处理与回退策略

public class SafeHTMLEditor {
    private JEditorPane editor;
    public void setHTMLContent(String html) {
        try {
            // 尝试直接设置
            editor.setText(HTMLSanitizer.preprocessHTML(html));
        } catch (RuntimeException e) {
            System.err.println("HTML parsing failed: " + e.getMessage());
            System.err.println("Falling back to plain text");
            // 回退:去除所有HTML标签
            String plainText = html.replaceAll("<[^>]*>", "");
            editor.setText(plainText);
            editor.setContentType("text/plain");
        }
    }
    public void setHTMLWithTimeout(String html, int timeoutMs) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<?> future = executor.submit(() -> {
            try {
                editor.setText(html);
            } catch (RuntimeException e) {
                throw new RuntimeException("Parsing failed", e);
            }
        });
        try {
            future.get(timeoutMs, TimeUnit.MILLISECONDS);
        } catch (TimeoutException e) {
            future.cancel(true);
            System.err.println("HTML parsing timed out");
        } catch (Exception e) {
            System.err.println("HTML parsing failed: " + e);
            editor.setText("Error rendering content");
        }
        executor.shutdown();
    }
}

使用更现代的替代方案

如果可能,考虑使用 Swing 以外的组件:

// 使用 JavaFX WebView(需要 JavaFX 环境)
// 或第三方库如 Flying Saucer (XHTML renderer)
// 或 SVG/PDF 渲染
// Flying Saucer 示例
public class FlyingSaucerRenderer {
    public static JComponent createFromXHTML(String xhtml) {
        try {
            JXPanel panel = new JXPanel();
            XHTMLPanel renderingPanel = new XHTMLPanel();
            renderingPanel.setDocument(xhtml, "");
            panel.add(renderingPanel);
            return panel;
        } catch (Exception e) {
            return new JLabel("Cannot render: " + e.getMessage());
        }
    }
}

调试技巧

// 开启详细日志
System.setProperty("sun.swing.exception.thread", "true");
System.setProperty("javax.swing.debug", "all");
// 捕获并记录原始HTML
public void debugHTMLParsing(String html) {
    try {
        editor.setText(html);
    } catch (RuntimeException e) {
        // 记录第一个出错的字符位置
        for (int i = 0; i < html.length(); i++) {
            if (html.codePointAt(i) > 127) {
                System.err.println("Non-ASCII at position " + i + ": " + 
                    Integer.toHexString(html.codePointAt(i)));
            }
        }
        // 使用XML解析器预检查
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.parse(new ByteArrayInputStream(html.getBytes("UTF-8")));
        } catch (Exception xmlEx) {
            System.err.println("XML validation failed: " + xmlEx.getMessage());
        }
    }
}

最佳实践建议

  1. 始终预处理输入 - 使用上述 sanitizer 方法
  2. 使用 Java 的内置 HTML 子集 - Swing 只支持 HTML 3.2 的基本子集
  3. 避免复杂的 CSS/JavaScript
  4. 设置同步加载优先级 - doc.setAsynchronousLoadPriority(-1)
  5. 缓存 - 解析好的内容可复用

如果问题持续存在,请提供触发异常的示例 HTML 内容,以便更准确地诊断问题。

抱歉,评论功能暂时关闭!