ik-analyzer新增词库后,需要重启solr,而线上环境肯定是需要支持热更新的,需要修改词库后“实时”更新词库。个人将先前修改后的IK(支持solr6.6+版本),再做修改,使之能实现以下功能:
- 支持IK词库热更新,服务定期扫描词库,发现词库变化则重新导入相应词库;
- 记录详细更新日志,新增时间+新增词语,方便定位问题;
- 支持禁用内置主词典main2012.dic。
1、DefaultConfig主要修改代码:
/**
* 获取词典动态更新时间间隔[首次延时,时间间隔](格式:正整数,单位:分钟)
*
* @return Integer 时间间隔
*/
public Integer[] getDicUpdateMin() {
String extUpdateMin = props.getProperty(DIC_UPDATEMIN);
Integer[] timeInterval = null;
if (null != extUpdateMin && !Objects.equals("", extUpdateMin.trim())) {
String[] split = extUpdateMin.split(",");
if (split.length == 2) {
timeInterval = new Integer[2];
timeInterval[0] = Integer.valueOf(split[0].trim());
timeInterval[1] = Integer.valueOf(split[1].trim());
if (timeInterval[1] <= 0) {
timeInterval = null;
}
}
}
Dictionary.print("dic_updateMin_Param", extUpdateMin);
return timeInterval;
}
/**
* 是否禁用内置主词典main2012.dic
*
* @return bool 默认false(不禁用)
*/
public boolean isDicDisable() {
String extUpdateMin = props.getProperty(DICINNER_DISABLE);
Dictionary.print("isDicDisable", extUpdateMin);
return Objects.equals("true", extUpdateMin);
}
2、Dictionary词典管理类
重构部分代码,主要修改代码如下:
/**
* 词典管理类,单子模式
*/
public class Dictionary {
/*
* 词典单子实例
*/
private static Dictionary singleton;
/*
* 主词典对象
*/
private static DictSegment _MainDict = null;
/*
* 停止词词典
*/
private static DictSegment _StopWordDict = null;
/*
* 量词词典
*/
private DictSegment _QuantifierDict;
/**
* 词典上传修改时间.
*/
private static Map<String, Long> dicLastModified = new HashMap<String, Long>();
/**
* 扩展词.
*/
private static Set<String> dicExtSet = new HashSet<String>(10000);
/**
* 停用词.
*/
private static Set<String> dicStopSet = new HashSet<String>(2000);
/**
* 配置对象
*/
private static Configuration cfg;
/**
* 线程池定时加载词典.
*/
private static ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(1);
/**
* 是否已加载过词典.
*/
private static boolean hasAdd = false;
/**
* SimpleDateFormat(程序逻辑不存在并发,不考虑线程不安全情况).
*/
private final static java.text.SimpleDateFormat DATE_FORMAT = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
/**
* 词典初始化
*
* 由于IK Analyzer的词典采用Dictionary类的静态方法进行词典初始化
*
* 只有当Dictionary类被实际调用时,才会开始载入词典, 这将延长首次分词操作的时间,
*
* 该方法提供了一个在应用加载阶段就初始化字典的手段
*
* @return Dictionary
*/
public static Dictionary initial(Configuration cfg) {
if (singleton == null) {
synchronized