本文目录导读:

我来详细介绍一下 JEditorPane、HTMLEditorKit 和 ParserInterceptor 拦截器的关系与使用。
基本概念
组件关系
JEditorPane (显示组件)
↓ 使用
HTMLEditorKit (HTML编辑器)
↓ 包含
Parser (HTML解析器)
↓ 回调
ParserInterceptor (解析拦截器)
ParserInterceptor 详解
基本接口定义
public interface ParserInterceptor {
// 拦截标签开始
Object interceptTaggedElement(Tag tag, HTML.Tag t, MutableAttributeSet a, int pos);
// 拦截文本内容
Object interceptTextContent(Tag tag, int startPos, int endPos);
// 定义拦截策略
int getPriority();
}
实际使用示例
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.text.html.*;
import javax.swing.text.html.parser.*;
public class HTMLInterceptorExample {
public static void main(String[] args) {
JEditorPane editorPane = new JEditorPane();
editorPane.setEditable(false);
// 创建HTML编辑器工具
HTMLEditorKit kit = new HTMLEditorKit() {
@Override
public ParserInterceptor getParserInterceptor() {
return new CustomParserInterceptor();
}
};
editorPane.setEditorKit(kit);
String html = "<html><body><h1>Title</h1><p>Content</p></body></html>";
editorPane.setText(html);
JFrame frame = new JFrame("HTML Interceptor Demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(editorPane));
frame.setSize(400, 300);
frame.setVisible(true);
}
}
// 自定义拦截器
class CustomParserInterceptor implements ParserInterceptor {
private boolean showDebug = true;
@Override
public Object interceptTaggedElement(Tag tag, HTML.Tag t,
MutableAttributeSet a, int pos) {
if (showDebug) {
System.out.println("拦截标签: " + t);
System.out.println("位置: " + pos);
System.out.println("属性: " + a);
}
// 可以修改标签行为
if (t == HTML.Tag.IMG) {
// 拦截图片标签,可以做特殊处理
System.out.println("图片标签被拦截");
return Boolean.TRUE; // 允许继续解析
}
return null; // 返回null表示使用默认行为
}
@Override
public Object interceptTextContent(Tag tag, int startPos, int endPos) {
if (showDebug) {
System.out.println("拦截文本内容: " + tag +
" [" + startPos + "-" + endPos + "]");
}
// 可以过滤或修改文本内容
return null;
}
@Override
public int getPriority() {
return 10; // 优先级
}
}
高级应用示例
HTML内容过滤
class ContentFilterInterceptor implements ParserInterceptor {
private List<String> blockedTags = Arrays.asList("script", "iframe");
private List<String> blockedAttributes = Arrays.asList("onclick", "onload");
@Override
public Object interceptTaggedElement(Tag tag, HTML.Tag t,
MutableAttributeSet a, int pos) {
// 过滤危险标签
if (blockedTags.contains(t.toString().toLowerCase())) {
System.out.println("阻止危险标签: " + t);
return Boolean.FALSE; // 阻止解析
}
// 过滤危险属性
Enumeration<?> names = a.getAttributeNames();
while (names.hasMoreElements()) {
Object name = names.nextElement();
if (blockedAttributes.contains(name.toString().toLowerCase())) {
a.removeAttribute(name);
System.out.println("移除危险属性: " + name);
}
}
return null;
}
@Override
public Object interceptTextContent(Tag tag, int startPos, int endPos) {
return null;
}
@Override
public int getPriority() {
return 100;
}
}
链接拦截处理
class LinkInterceptor implements ParserInterceptor {
@Override
public Object interceptTaggedElement(Tag tag, HTML.Tag t,
MutableAttributeSet a, int pos) {
if (t == HTML.Tag.A) {
String href = (String) a.getAttribute(HTML.Attribute.HREF);
if (href != null && href.startsWith("http://")) {
System.out.println("检测到外部链接: " + href);
// 可以添加自定义属性
a.addAttribute("data-external", "true");
}
}
return null;
}
@Override
public Object interceptTextContent(Tag tag, int startPos, int endPos) {
return null;
}
@Override
public int getPriority() {
return 50;
}
}
性能监控拦截器
class PerformanceMonitorInterceptor implements ParserInterceptor {
private long startTime;
private Map<String, Integer> tagCount = new HashMap<>();
@Override
public Object interceptTaggedElement(Tag tag, HTML.Tag t,
MutableAttributeSet a, int pos) {
if (startTime == 0) {
startTime = System.currentTimeMillis();
}
// 统计标签数量
String tagName = t.toString();
tagCount.put(tagName, tagCount.getOrDefault(tagName, 0) + 1);
return null;
}
@Override
public Object interceptTextContent(Tag tag, int startPos, int endPos) {
return null;
}
@Override
public int getPriority() {
return Integer.MIN_VALUE;
}
public void printStatistics() {
long endTime = System.currentTimeMillis();
System.out.println("解析耗时: " + (endTime - startTime) + "ms");
System.out.println("标签统计: " + tagCount);
}
}
实用技巧
注册多个拦截器
class MultiInterceptorParser extends HTMLEditorKit.Parser {
private List<ParserInterceptor> interceptors = new ArrayList<>();
public void addInterceptor(ParserInterceptor interceptor) {
interceptors.add(interceptor);
// 按优先级排序
interceptors.sort((a, b) -> b.getPriority() - a.getPriority());
}
// 调用所有拦截器
private void notifyInterceptors(Tag tag, HTML.Tag t,
MutableAttributeSet a, int pos) {
for (ParserInterceptor interceptor : interceptors) {
Object result = interceptor.interceptTaggedElement(tag, t, a, pos);
if (result == Boolean.FALSE) {
break; // 拦截器阻止继续处理
}
}
}
}
动态修改内容
class ContentModifierInterceptor implements ParserInterceptor {
private static final Pattern LINK_PATTERN =
Pattern.compile("https?://[\\w\\.-]+(/[\\w\\./-]+)*");
@Override
public Object interceptTextContent(Tag tag, int startPos, int endPos) {
// 可以在这里处理文本内容
return null;
}
@Override
public Object interceptTaggedElement(Tag tag, HTML.Tag t,
MutableAttributeSet a, int pos) {
// 添加自定义CSS类
if (t == HTML.Tag.P) {
a.addAttribute(HTML.Attribute.CLASS, "custom-paragraph");
}
// 修改图片大小
if (t == HTML.Tag.IMG) {
a.addAttribute(HTML.Attribute.WIDTH, "100%");
a.addAttribute(HTML.Attribute.HEIGHT, "auto");
}
return null;
}
@Override
public int getPriority() {
return 75;
}
}
注意事项
- 性能影响:拦截器会增加解析开销,避免在回调中执行耗时操作
- 线程安全:解析过程可能在非EDT线程执行,注意线程安全
- 版本兼容:不同JDK版本的实现可能有差异
- 测试重要性:不同HTML内容可能触发不同行为,需要充分测试
这个拦截器机制为JEditorPane处理HTML提供了强大的扩展点,可以用于安全过滤、功能增强、性能监控等场景。