应项目需要,网上找到富文本转纯文本的工具代码,原文链接为[java将富文本字符串(HTML)转为文本(Text)
解决了项目上的一个需求,但是分析发现代码中的stringbuffer存在线程安全问题.并发访问时,会存在另一个线程传入的文本将其他线程使用的文本更改的问题,因此对代码进行了改进如下.
import lombok.extern.slf4j.Slf4j;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.parser.ParserDelegator;
import java.io.*;
@Slf4j
public class Html2Text extends HTMLEditorKit.ParserCallback {
private static final Html2Text html2Text = new Html2Text();
ThreadLocal<StringBuffer> sb = new ThreadLocal<>();
private Html2Text() {
}
public static String getContent(String str) {
try {
html2Text.parse(str);
} catch (IOException e) {
log.error("解析html异常", e);
}
return html2Text.getText();
}
public void parse(String str) throws IOException {
try (Reader in = new InputStreamReader(new ByteArrayInputStream(str.getBytes()))) {
sb.set(new StringBuffer());
ParserDelegator delegator = new ParserDelegator();
delegator.parse(in, this, Boolean.TRUE); // the third parameter is TRUE to ignore charset directive
}
}
/**
*
* @param text
* @param pos
*/
@Override
public void handleText(char[] text, int pos) {
sb.get().append( text ).append( "\n" );
}
private String getText() {
return sb.get().toString();
}
public static void main(String[] args) {
String htmlStr = "这里输入测试的html文本";
String content = getContent(htmlStr);
System.out.println(content);
}
}
在main方法中构造了一个线程池,启动两个任务.其中一个任务的文本含有test1前缀,并在getText()方法中加入了对含有test1前缀时,对当前线程停止10s的测试.测试结果显示改造前的代码,线程之间的不同文本会互相干扰. 改造后,线程之间没有发生该问题.测试代码略.