我正在处理CMS的HttpServlet扩展(插件),其任务是过滤HTML响应。
在我的filterResponse
方法中,我在字符串中获取请求的text/html
,这是其中的三个参数之一。
具体来说,我需要做的是在html字符串中搜索特定的URL模式并稍微修改它。现在,当大型文档中有许多链接时,这可能是一个繁重的操作,我想尽可能地优化这个过程。
我的第一个版本只是在String上使用了replace("://www.", "://www-x1.")
方法。
然后,在当前版本中,我使用Matcher
和Pattern
类。
示例代码:
@Override
public String filterResponse(HttpServletRequest request, String textHtml, String contentType) throws Exception {
Pattern pattern = Pattern.compile("://www.");
Matcher m = pattern.matcher(textHtml);
String response = m.replaceAll("://www-x1.");
.....
.....
return response;
}
在现实世界的代码中,我在静态字段中预编译模式(Pattern),并对匹配的字符串执行相同的操作。
关于如何加快速度的任何想法? 也许转换为DOM对象或其他一些XML对象以获得更快的查询方法?等
答案 0 :(得分:0)
首先,您在没有模式的情况下使用模式匹配。这不仅浪费性能,而且是一个错误。对于用作模式的"://www."
,最后一个点匹配任何字符。
如果您想要替换简单的String
而不是模式,则可以使用String.replace
代替String.replaceAll
。这样可以解决错误并节省内部创建Pattern
和Matcher
的全部费用。
如果要使用正则表达式匹配器,最简单的解决方法是使用Pattern.compile("://www.", Pattern.LITERAL)
来停止解释特殊字符,并允许对整个序列使用Boyer-Moore算法。但是,如果您可以存储和重复使用准备好的模式,这只会得到回报。
此外,replaceAll
方法提供了在替换String
中解释对匹配组的反向引用的功能。由于您没有使用此功能,因此您可以通过自己实施替换循环来节省与该功能相关的开销。作为奖励,您可以StringBuilder
使用Matcher
使用StringBuffer
,但这只是一个小改进。
static String replace(String source)
{// the pattern would be better off being re-usable stored in a static field
final Pattern pattern = Pattern.compile("://www.", Pattern.LITERAL);
final Matcher m = pattern.matcher(source);
boolean result = m.find();
if (result) {
StringBuilder sb = new StringBuilder(source.length()+16);
int p=0;
do {
sb.append(source, p, m.start()).append("://www-x1.");
p=m.end();
} while (m.find());
sb.append(source, p, source.length());
return sb.toString();
}
return source;
}
但正如已经说过的那样,完全没有使用正则表达式可能是这个简单案例的更好选择。