花了整整一天时间,将Lucene5中有关索引的常见操作进行了简单封装,废话不多说,上代码:
1package com.yida.framework.lucene5.util; 2 3import java.io.IOException; 4import java.util.concurrent.ExecutorService; 5import java.util.concurrent.locks.Lock; 6import java.util.concurrent.locks.ReentrantLock; 7 8import org.apache.lucene.index.DirectoryReader; 9import org.apache.lucene.index.IndexReader; 10import org.apache.lucene.index.IndexWriter; 11import org.apache.lucene.index.IndexWriterConfig; 12import org.apache.lucene.search.IndexSearcher; 13import org.apache.lucene.store.Directory; 14import org.apache.lucene.store.LockObtainFailedException; 15/** 16 * Lucene索引读写器/查询器单例获取工具类 17 * @author Lanxiaowei 18 * 19 */ 20public class LuceneManager { 21 private volatile static LuceneManager singleton; 22 23 private volatile static IndexWriter writer; 24 25 private volatile static IndexReader reader; 26 27 private volatile static IndexSearcher searcher; 28 29 private final Lock writerLock = new ReentrantLock(); 30 31 //private final Lock readerLock = new ReentrantLock(); 32 33 //private final Lock searcherLock = new ReentrantLock(); 34 35 private LuceneManager() {} 36 37 public static LuceneManager getInstance() { 38 if (null == singleton) { 39 synchronized (LuceneManager.class) { 40 if (null == singleton) { 41 singleton = new LuceneManager(); 42 } 43 } 44 } 45 return singleton; 46 } 47 48 /** 49 * 获取IndexWriter单例对象 50 * @param dir 51 * @param config 52 * @return 53 */ 54 public IndexWriter getIndexWriter(Directory dir, IndexWriterConfig config) { 55 if(null == dir) { 56 throw new IllegalArgumentException("Directory can not be null."); 57 } 58 if(null == config) { 59 throw new IllegalArgumentException("IndexWriterConfig can not be null."); 60 } 61 try { 62 writerLock.lock(); 63 if(null == writer){ 64 //如果索引目录被锁,则直接抛异常 65 if(IndexWriter.isLocked(dir)) { 66 throw new LockObtainFailedException("Directory of index had been locked."); 67 } 68 writer = new IndexWriter(dir, config); 69 } 70 } catch (LockObtainFailedException e) { 71 e.printStackTrace(); 72 } catch (IOException e) { 73 e.printStackTrace(); 74 } finally { 75 writerLock.unlock(); 76 } 77 return writer; 78 } 79 80 /** 81 * 获取IndexReader对象 82 * @param dir 83 * @param enableNRTReader 是否开启NRTReader 84 * @return 85 */ 86 public IndexReader getIndexReader(Directory dir,boolean enableNRTReader) { 87 if(null == dir) { 88 throw new IllegalArgumentException("Directory can not be null."); 89 } 90 try { 91 if(null == reader){ 92 reader = DirectoryReader.open(dir); 93 } else { 94 if(enableNRTReader && reader instanceof DirectoryReader) { 95 //开启近实时Reader,能立即看到动态添加/删除的索引变化 96 reader = DirectoryReader.openIfChanged((DirectoryReader)reader); 97 } 98 } 99 } catch (IOException e) { 100 e.printStackTrace(); 101 } 102 return reader; 103 } 104 105 /** 106 * 获取IndexReader对象(默认不启用NETReader) 107 * @param dir 108 * @return 109 */ 110 public IndexReader getIndexReader(Directory dir) { 111 return getIndexReader(dir, false); 112 } 113 114 /** 115 * 获取IndexSearcher对象 116 * @param reader IndexReader对象实例 117 * @param executor 如果你需要开启多线程查询,请提供ExecutorService对象参数 118 * @return 119 */ 120 public IndexSearcher getIndexSearcher(IndexReader reader,ExecutorService executor) { 121 if(null == reader) { 122 throw new IllegalArgumentException("The indexReader can not be null."); 123 } 124 if(null == searcher){ 125 searcher = new IndexSearcher(reader); 126 } 127 return searcher; 128 } 129 130 /** 131 * 获取IndexSearcher对象(不支持多线程查询) 132 * @param reader IndexReader对象实例 133 * @return 134 */ 135 public IndexSearcher getIndexSearcher(IndexReader reader) { 136 return getIndexSearcher(reader, null); 137 } 138} 139package com.yida.framework.lucene5.util; 140 141import java.io.IOException; 142import java.nio.file.Paths; 143import java.util.ArrayList; 144import java.util.Collections; 145import java.util.List; 146import java.util.Set; 147import java.util.concurrent.ExecutorService; 148 149import org.ansj.lucene5.AnsjAnalyzer; 150import org.apache.lucene.analysis.Analyzer; 151import org.apache.lucene.document.Document; 152import org.apache.lucene.document.Field; 153import org.apache.lucene.document.TextField; 154import org.apache.lucene.index.IndexReader; 155import org.apache.lucene.index.IndexWriter; 156import org.apache.lucene.index.IndexWriterConfig; 157import org.apache.lucene.index.IndexableField; 158import org.apache.lucene.index.Term; 159import org.apache.lucene.queryparser.classic.QueryParser; 160import org.apache.lucene.search.IndexSearcher; 161import org.apache.lucene.search.Query; 162import org.apache.lucene.search.ScoreDoc; 163import org.apache.lucene.search.TopDocs; 164import org.apache.lucene.search.highlight.Formatter; 165import org.apache.lucene.search.highlight.Fragmenter; 166import org.apache.lucene.search.highlight.Highlighter; 167import org.apache.lucene.search.highlight.InvalidTokenOffsetsException; 168import org.apache.lucene.search.highlight.QueryScorer; 169import org.apache.lucene.search.highlight.Scorer; 170import org.apache.lucene.search.highlight.SimpleFragmenter; 171import org.apache.lucene.search.highlight.SimpleHTMLFormatter; 172import org.apache.lucene.store.Directory; 173import org.apache.lucene.store.FSDirectory; 174 175/** 176 * Lucene工具类(基于Lucene5.0封装) 177 * @author Lanxiaowei 178 * 179 */ 180public class LuceneUtils { 181 private static final LuceneManager luceneManager = LuceneManager.getInstance(); 182 private static Analyzer analyzer = new AnsjAnalyzer(); 183 184 /** 185 * 打开索引目录 186 * 187 * @param luceneDir 188 * @return 189 * @throws IOException 190 */ 191 public static FSDirectory openFSDirectory(String luceneDir) { 192 FSDirectory directory = null; 193 try { 194 directory = FSDirectory.open(Paths.get(luceneDir)); 195 /** 196 * 注意:isLocked方法内部会试图去获取Lock,如果获取到Lock,会关闭它,否则return false表示索引目录没有被锁, 197 * 这也就是为什么unlock方法被从IndexWriter类中移除的原因 198 */ 199 IndexWriter.isLocked(directory); 200 } catch (IOException e) { 201 e.printStackTrace(); 202 } 203 return directory; 204 } 205 206 /** 207 * 关闭索引目录并销毁 208 * @param directory 209 * @throws IOException 210 */ 211 public static void closeDirectory(Directory directory) throws IOException { 212 if (null != directory) { 213 directory.close(); 214 directory = null; 215 } 216 } 217 218 /** 219 * 获取IndexWriter 220 * @param dir 221 * @param config 222 * @return 223 */ 224 public static IndexWriter getIndexWrtier(Directory dir, IndexWriterConfig config) { 225 return luceneManager.getIndexWriter(dir, config); 226 } 227 228 /** 229 * 获取IndexWriter 230 * @param dir 231 * @param config 232 * @return 233 */ 234 public static IndexWriter getIndexWrtier(String directoryPath, IndexWriterConfig config) { 235 FSDirectory directory = openFSDirectory(directoryPath); 236 return luceneManager.getIndexWriter(directory, config); 237 } 238 239 /** 240 * 获取IndexReader 241 * @param dir 242 * @param enableNRTReader 是否开启NRTReader 243 * @return 244 */ 245 public static IndexReader getIndexReader(Directory dir,boolean enableNRTReader) { 246 return luceneManager.getIndexReader(dir, enableNRTReader); 247 } 248 249 /** 250 * 获取IndexReader(默认不启用NRTReader) 251 * @param dir 252 * @return 253 */ 254 public static IndexReader getIndexReader(Directory dir) { 255 return luceneManager.getIndexReader(dir); 256 } 257 258 /** 259 * 获取IndexSearcher 260 * @param reader IndexReader对象 261 * @param executor 如果你需要开启多线程查询,请提供ExecutorService对象参数 262 * @return 263 */ 264 public static IndexSearcher getIndexSearcher(IndexReader reader,ExecutorService executor) { 265 return luceneManager.getIndexSearcher(reader, executor); 266 } 267 268 /** 269 * 获取IndexSearcher(不支持多线程查询) 270 * @param reader IndexReader对象 271 * @return 272 */ 273 public static IndexSearcher getIndexSearcher(IndexReader reader) { 274 return luceneManager.getIndexSearcher(reader); 275 } 276 277 /** 278 * 创建QueryParser对象 279 * @param field 280 * @param analyzer 281 * @return 282 */ 283 public static QueryParser createQueryParser(String field, Analyzer analyzer) { 284 return new QueryParser(field, analyzer); 285 } 286 287 /** 288 * 关闭IndexReader 289 * @param reader 290 */ 291 public static void closeIndexReader(IndexReader reader) { 292 if (null != reader) { 293 try { 294 reader.close(); 295 reader = null; 296 } catch (IOException e) { 297 e.printStackTrace(); 298 } 299 } 300 } 301 302 /** 303 * 关闭IndexWriter 304 * @param writer 305 */ 306 public static void closeIndexWriter(IndexWriter writer) { 307 if(null != writer) { 308 try { 309 writer.close(); 310 writer = null; 311 } catch (IOException e) { 312 e.printStackTrace(); 313 } 314 } 315 } 316 317 /** 318 * 关闭IndexReader和IndexWriter 319 * @param reader 320 * @param writer 321 */ 322 public static void closeAll(IndexReader reader, IndexWriter writer) { 323 closeIndexReader(reader); 324 closeIndexWriter(writer); 325 } 326 327 /** 328 * 删除索引[注意:请自己关闭IndexWriter对象] 329 * @param writer 330 * @param field 331 * @param value 332 */ 333 public static void deleteIndex(IndexWriter writer, String field, String value) { 334 try { 335 writer.deleteDocuments(new Term[] {new Term(field,value)}); 336 } catch (IOException e) { 337 e.printStackTrace(); 338 } 339 } 340 341 /** 342 * 删除索引[注意:请自己关闭IndexWriter对象] 343 * @param writer 344 * @param query 345 */ 346 public static void deleteIndex(IndexWriter writer, Query query) { 347 try { 348 writer.deleteDocuments(query); 349 } catch (IOException e) { 350 e.printStackTrace(); 351 } 352 } 353 354 /** 355 * 批量删除索引[注意:请自己关闭IndexWriter对象] 356 * @param writer 357 * @param terms 358 */ 359 public static void deleteIndexs(IndexWriter writer,Term[] terms) { 360 try { 361 writer.deleteDocuments(terms); 362 } catch (IOException e) { 363 e.printStackTrace(); 364 } 365 } 366 367 /** 368 * 批量删除索引[注意:请自己关闭IndexWriter对象] 369 * @param writer 370 * @param querys 371 */ 372 public static void deleteIndexs(IndexWriter writer,Query[] querys) { 373 try { 374 writer.deleteDocuments(querys); 375 } catch (IOException e) { 376 e.printStackTrace(); 377 } 378 } 379 380 /** 381 * 删除所有索引文档 382 * @param writer 383 */ 384 public static void deleteAllIndex(IndexWriter writer) { 385 try { 386 writer.deleteAll(); 387 } catch (IOException e) { 388 e.printStackTrace(); 389 } 390 } 391 392 /** 393 * 更新索引文档 394 * @param writer 395 * @param term 396 * @param document 397 */ 398 public static void updateIndex(IndexWriter writer,Term term,Document document) { 399 try { 400 writer.updateDocument(term, document); 401 } catch (IOException e) { 402 e.printStackTrace(); 403 } 404 } 405 406 /** 407 * 更新索引文档 408 * @param writer 409 * @param term 410 * @param document 411 */ 412 public static void updateIndex(IndexWriter writer,String field,String value,Document document) { 413 updateIndex(writer, new Term(field, value), document); 414 } 415 416 /** 417 * 添加索引文档 418 * @param writer 419 * @param doc 420 */ 421 public static void addIndex(IndexWriter writer, Document document) { 422 updateIndex(writer, null, document); 423 } 424 425 /** 426 * 索引文档查询 427 * @param searcher 428 * @param query 429 * @return 430 */ 431 public static List<Document> query(IndexSearcher searcher,Query query) { 432 TopDocs topDocs = null; 433 try { 434 topDocs = searcher.search(query, Integer.MAX_VALUE); 435 } catch (IOException e) { 436 e.printStackTrace(); 437 } 438 ScoreDoc[] scores = topDocs.scoreDocs; 439 int length = scores.length; 440 if (length <= 0) { 441 return Collections.emptyList(); 442 } 443 List<Document> docList = new ArrayList<Document>(); 444 try { 445 for (int i = 0; i < length; i++) { 446 Document doc = searcher.doc(scores[i].doc); 447 docList.add(doc); 448 } 449 } catch (IOException e) { 450 e.printStackTrace(); 451 } 452 return docList; 453 } 454 455 /** 456 * 返回索引文档的总数[注意:请自己手动关闭IndexReader] 457 * @param reader 458 * @return 459 */ 460 public static int getIndexTotalCount(IndexReader reader) { 461 return reader.numDocs(); 462 } 463 464 /** 465 * 返回索引文档中最大文档ID[注意:请自己手动关闭IndexReader] 466 * @param reader 467 * @return 468 */ 469 public static int getMaxDocId(IndexReader reader) { 470 return reader.maxDoc(); 471 } 472 473 /** 474 * 返回已经删除尚未提交的文档总数[注意:请自己手动关闭IndexReader] 475 * @param reader 476 * @return 477 */ 478 public static int getDeletedDocNum(IndexReader reader) { 479 return getMaxDocId(reader) - getIndexTotalCount(reader); 480 } 481 482 /** 483 * 根据docId查询索引文档 484 * @param reader IndexReader对象 485 * @param docID documentId 486 * @param fieldsToLoad 需要返回的field 487 * @return 488 */ 489 public static Document findDocumentByDocId(IndexReader reader,int docID, Set<String> fieldsToLoad) { 490 try { 491 return reader.document(docID, fieldsToLoad); 492 } catch (IOException e) { 493 return null; 494 } 495 } 496 497 /** 498 * 根据docId查询索引文档 499 * @param reader IndexReader对象 500 * @param docID documentId 501 * @return 502 */ 503 public static Document findDocumentByDocId(IndexReader reader,int docID) { 504 return findDocumentByDocId(reader, docID, null); 505 } 506 507 /** 508 * @Title: createHighlighter 509 * @Description: 创建高亮器 510 * @param query 索引查询对象 511 * @param prefix 高亮前缀字符串 512 * @param stuffix 高亮后缀字符串 513 * @param fragmenterLength 摘要最大长度 514 * @return 515 */ 516 public static Highlighter createHighlighter(Query query, String prefix, String stuffix, int fragmenterLength) { 517 Formatter formatter = new SimpleHTMLFormatter((prefix == null || prefix.trim().length() == 0) ? 518 "<font color=\"red\">" : prefix, (stuffix == null || stuffix.trim().length() == 0)?"</font>" : stuffix); 519 Scorer fragmentScorer = new QueryScorer(query); 520 Highlighter highlighter = new Highlighter(formatter, fragmentScorer); 521 Fragmenter fragmenter = new SimpleFragmenter(fragmenterLength <= 0 ? 50 : fragmenterLength); 522 highlighter.setTextFragmenter(fragmenter); 523 return highlighter; 524 } 525 526 /** 527 * @Title: highlight 528 * @Description: 生成高亮文本 529 * @param document 索引文档对象 530 * @param highlighter 高亮器 531 * @param analyzer 索引分词器 532 * @param field 高亮字段 533 * @return 534 * @throws IOException 535 * @throws InvalidTokenOffsetsException 536 */ 537 public static String highlight(Document document,Highlighter highlighter,Analyzer analyzer,String field) throws IOException { 538 List<IndexableField> list = document.getFields(); 539 for (IndexableField fieldable : list) { 540 String fieldValue = fieldable.stringValue(); 541 if(fieldable.name().equals(field)) { 542 try { 543 fieldValue = highlighter.getBestFragment(analyzer, field, fieldValue); 544 } catch (InvalidTokenOffsetsException e) { 545 fieldValue = fieldable.stringValue(); 546 } 547 return (fieldValue == null || fieldValue.trim().length() == 0)? fieldable.stringValue() : fieldValue; 548 } 549 } 550 return null; 551 } 552 553 /** 554 * @Title: searchTotalRecord 555 * @Description: 获取符合条件的总记录数 556 * @param query 557 * @return 558 * @throws IOException 559 */ 560 public static int searchTotalRecord(IndexSearcher search,Query query) { 561 ScoreDoc[] docs = null; 562 try { 563 TopDocs topDocs = search.search(query, Integer.MAX_VALUE); 564 if(topDocs == null || topDocs.scoreDocs == null || topDocs.scoreDocs.length == 0) { 565 return 0; 566 } 567 docs = topDocs.scoreDocs; 568 } catch (IOException e) { 569 e.printStackTrace(); 570 } 571 return docs.length; 572 } 573 574 /** 575 * @Title: pageQuery 576 * @Description: Lucene分页查询 577 * @param searcher 578 * @param query 579 * @param page 580 * @throws IOException 581 */ 582 public static void pageQuery(IndexSearcher searcher,Directory directory,Query query,Page<Document> page) { 583 int totalRecord = searchTotalRecord(searcher,query); 584 //设置总记录数 585 page.setTotalRecord(totalRecord); 586 TopDocs topDocs = null; 587 try { 588 topDocs = searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize()); 589 } catch (IOException e) { 590 e.printStackTrace(); 591 } 592 List<Document> docList = new ArrayList<Document>(); 593 ScoreDoc[] docs = topDocs.scoreDocs; 594 int index = 0; 595 for (ScoreDoc scoreDoc : docs) { 596 int docID = scoreDoc.doc; 597 Document document = null; 598 try { 599 document = searcher.doc(docID); 600 } catch (IOException e) { 601 e.printStackTrace(); 602 } 603 if(index == docs.length - 1) { 604 page.setAfterDoc(scoreDoc); 605 page.setAfterDocId(docID); 606 } 607 docList.add(document); 608 index++; 609 } 610 page.setItems(docList); 611 closeIndexReader(searcher.getIndexReader()); 612 } 613 614 /** 615 * @Title: pageQuery 616 * @Description: 分页查询[如果设置了高亮,则会更新索引文档] 617 * @param searcher 618 * @param directory 619 * @param query 620 * @param page 621 * @param highlighterParam 622 * @param writerConfig 623 * @throws IOException 624 */ 625 public static void pageQuery(IndexSearcher searcher,Directory directory,Query query,Page<Document> page,HighlighterParam highlighterParam,IndexWriterConfig writerConfig) throws IOException { 626 IndexWriter writer = null; 627 //若未设置高亮 628 if(null == highlighterParam || !highlighterParam.isHighlight()) { 629 pageQuery(searcher,directory,query, page); 630 } else { 631 int totalRecord = searchTotalRecord(searcher,query); 632 System.out.println("totalRecord:" + totalRecord); 633 //设置总记录数 634 page.setTotalRecord(totalRecord); 635 TopDocs topDocs = searcher.searchAfter(page.getAfterDoc(),query, page.getPageSize()); 636 List<Document> docList = new ArrayList<Document>(); 637 ScoreDoc[] docs = topDocs.scoreDocs; 638 int index = 0; 639 writer = getIndexWrtier(directory, writerConfig); 640 for (ScoreDoc scoreDoc : docs) { 641 int docID = scoreDoc.doc; 642 Document document = searcher.doc(docID); 643 String content = document.get(highlighterParam.getFieldName()); 644 if(null != content && content.trim().length() > 0) { 645 //创建高亮器 646 Highlighter highlighter = LuceneUtils.createHighlighter(query, 647 highlighterParam.getPrefix(), highlighterParam.getStuffix(), 648 highlighterParam.getFragmenterLength()); 649 String text = highlight(document, highlighter, analyzer, highlighterParam.getFieldName()); 650 //若高亮后跟原始文本不相同,表示高亮成功 651 if(!text.equals(content)) { 652 Document tempdocument = new Document(); 653 List<IndexableField> indexableFieldList = document.getFields(); 654 if(null != indexableFieldList && indexableFieldList.size() > 0) { 655 for(IndexableField field : indexableFieldList) { 656 if(field.name().equals(highlighterParam.getFieldName())) { 657 tempdocument.add(new TextField(field.name(), text, Field.Store.YES)); 658 } else { 659 tempdocument.add(field); 660 } 661 } 662 } 663 updateIndex(writer, new Term(highlighterParam.getFieldName(),content), tempdocument); 664 document = tempdocument; 665 } 666 } 667 if(index == docs.length - 1) { 668 page.setAfterDoc(scoreDoc); 669 page.setAfterDocId(docID); 670 } 671 docList.add(document); 672 index++; 673 } 674 page.setItems(docList); 675 } 676 closeIndexReader(searcher.getIndexReader()); 677 closeIndexWriter(writer); 678 } 679} 680package com.yida.framework.lucene5.util; 681import java.util.ArrayList; 682import java.util.Collection; 683import java.util.List; 684import org.apache.lucene.document.Document; 685import org.apache.lucene.search.ScoreDoc; 686public class Page<T> { 687 /**当前第几页(从1开始计算)*/ 688 private int currentPage; 689 /**每页显示几条*/ 690 private int pageSize; 691 /**总记录数*/ 692 private int totalRecord; 693 /**总页数*/ 694 private int totalPage; 695 /**分页数据集合[用泛型T来限定集合元素类型]*/ 696 private Collection<T> items; 697 /**当前显示起始索引(从零开始计算)*/ 698 private int startIndex; 699 /**当前显示结束索引(从零开始计算)*/ 700 private int endIndex; 701 /**一组最多显示几个页码[比如Google一组最多显示10个页码]*/ 702 private int groupSize; 703 /**左边偏移量*/ 704 private int leftOffset = 5; 705 /**右边偏移量*/ 706 private int rightOffset = 4; 707 /**当前页码范围*/ 708 private String[] pageRange; 709 /**分页数据*/ 710 private List<Document> docList; 711 /**上一页最后一个ScoreDoc对象*/ 712 private ScoreDoc afterDoc; 713 /**上一页最后一个ScoreDoc对象的Document对象ID*/ 714 private int afterDocId; 715 public void setRangeIndex() { 716 int groupSize = getGroupSize(); 717 int totalPage = getTotalPage(); 718 if(totalPage < 2) { 719 startIndex = 0; 720 endIndex = totalPage - startIndex; 721 } else { 722 int currentPage = getCurrentPage(); 723 if(groupSize >= totalPage) { 724 startIndex = 0; 725 endIndex = totalPage - startIndex - 1; 726 } else { 727 int leftOffset = getLeftOffset(); 728 int middleOffset = getMiddleOffset(); 729 if(-1 == middleOffset) { 730 startIndex = 0; 731 endIndex = groupSize - 1; 732 } else if(currentPage <= leftOffset) { 733 startIndex = 0; 734 endIndex = groupSize - 1; 735 } else { 736 startIndex = currentPage - leftOffset - 1; 737 if(currentPage + rightOffset > totalPage) { 738 endIndex = totalPage - 1; 739 } else { 740 endIndex = currentPage + rightOffset - 1; 741 } 742 } 743 } 744 } 745 } 746 public int getCurrentPage() { 747 if(currentPage <= 0) { 748 currentPage = 1; 749 } else { 750 int totalPage = getTotalPage(); 751 if(totalPage > 0 && currentPage > getTotalPage()) { 752 currentPage = totalPage; 753 } 754 } 755 return currentPage; 756 } 757 public void setCurrentPage(int currentPage) { 758 this.currentPage = currentPage; 759 } 760 public int getPageSize() { 761 if(pageSize <= 0) { 762 pageSize = 10; 763 } 764 return pageSize; 765 } 766 public void setPageSize(int pageSize) { 767 this.pageSize = pageSize; 768 } 769 public int getTotalRecord() { 770 return totalRecord; 771 } 772 public void setTotalRecord(int totalRecord) { 773 this.totalRecord = totalRecord; 774 } 775 public int getTotalPage() { 776 int totalRecord = getTotalRecord(); 777 if(totalRecord == 0) { 778 totalPage = 0; 779 } else { 780 int pageSize = getPageSize(); 781 totalPage = totalRecord % pageSize == 0 ? totalRecord / pageSize : (totalRecord / pageSize) + 1; 782 } 783 return totalPage; 784 } 785 public void setTotalPage(int totalPage) { 786 this.totalPage = totalPage; 787 } 788 public int getStartIndex() { 789 return startIndex; 790 } 791 public void setStartIndex(int startIndex) { 792 this.startIndex = startIndex; 793 } 794 public int getEndIndex() { 795 return endIndex; 796 } 797 public void setEndIndex(int endIndex) { 798 this.endIndex = endIndex; 799 } 800 public int getGroupSize() { 801 if(groupSize <= 0) { 802 groupSize = 10; 803 } 804 return groupSize; 805 } 806 public void setGroupSize(int groupSize) { 807 this.groupSize = groupSize; 808 } 809 public int getLeftOffset() { 810 leftOffset = getGroupSize() / 2; 811 return leftOffset; 812 } 813 public void setLeftOffset(int leftOffset) { 814 this.leftOffset = leftOffset; 815 } 816 public int getRightOffset() { 817 int groupSize = getGroupSize(); 818 if(groupSize % 2 == 0) { 819 rightOffset = (groupSize / 2) - 1; 820 } else { 821 rightOffset = groupSize / 2; 822 } 823 return rightOffset; 824 } 825 public void setRightOffset(int rightOffset) { 826 this.rightOffset = rightOffset; 827 } 828 /**中心位置索引[从1开始计算]*/ 829 public int getMiddleOffset() { 830 int groupSize = getGroupSize(); 831 int totalPage = getTotalPage(); 832 if(groupSize >= totalPage) { 833 return -1; 834 } 835 return getLeftOffset() + 1; 836 } 837 public String[] getPageRange() { 838 setRangeIndex(); 839 int size = endIndex - startIndex + 1; 840 if(size <= 0) { 841 return new String[0]; 842 } 843 if(totalPage == 1) { 844 return new String[] {"1"}; 845 } 846 pageRange = new String[size]; 847 for(int i=0; i < size; i++) { 848 pageRange[i] = (startIndex + i + 1) + ""; 849 } 850 return pageRange; 851 } 852 public void setPageRange(String[] pageRange) { 853 this.pageRange = pageRange; 854 } 855 public Collection<T> getItems() { 856 return items; 857 } 858 public void setItems(Collection<T> items) { 859 this.items = items; 860 } 861 public List<Document> getDocList() { 862 return docList; 863 } 864 public void setDocList(List<Document> docList) { 865 this.docList = docList; 866 } 867 public ScoreDoc getAfterDoc() { 868 setAfterDocId(afterDocId); 869 return afterDoc; 870 } 871 public void setAfterDoc(ScoreDoc afterDoc) { 872 this.afterDoc = afterDoc; 873 } 874 public int getAfterDocId() { 875 return afterDocId; 876 } 877 public void setAfterDocId(int afterDocId) { 878 this.afterDocId = afterDocId; 879 if(null == afterDoc) { 880 this.afterDoc = new ScoreDoc(afterDocId, 1.0f); 881 } 882 } 883 public Page() {} 884 public Page(int currentPage, int pageSize) { 885 this.currentPage = currentPage; 886 this.pageSize = pageSize; 887 } 888 public Page(int currentPage, int pageSize, Collection<T> items) { 889 this.currentPage = currentPage; 890 this.pageSize = pageSize; 891 this.items = items; 892 } 893 public Page(int currentPage, int pageSize, Collection<T> items, int groupSize) { 894 this.currentPage = currentPage; 895 this.pageSize = pageSize; 896 this.items = items; 897 this.groupSize = groupSize; 898 } 899 public Page(int currentPage, int pageSize, int groupSize, int afterDocId) { 900 this.currentPage = currentPage; 901 this.pageSize = pageSize; 902 this.groupSize = groupSize; 903 this.afterDocId = afterDocId; 904 } 905 public static void main(String[] args) { 906 Collection<Integer> items = new ArrayList<Integer>(); 907 int totalRecord = 201; 908 for(int i=0; i < totalRecord; i++) { 909 items.add(new Integer(i)); 910 } 911 Page<Integer> page = new Page<Integer>(1,10,items,10); 912 page.setTotalRecord(totalRecord); 913 int totalPage = page.getTotalPage(); 914 for(int i=0; i < totalPage; i++) { 915 page.setCurrentPage(i+1); 916 String[] pageRange = page.getPageRange(); 917 System.out.println("当前第" + page.currentPage + "页"); 918 for(int j=0; j < pageRange.length; j++) { 919 System.out.print(pageRange[j] + " "); 920 } 921 System.out.println("\n"); 922 } 923 } 924} 925package com.yida.framework.lucene5.util; 926/** 927 * @ClassName: HighlighterParam 928 * @Description: 高亮器参数对象 929 * @author Lanxiaowei 930 * @date 2014-3-30 下午12:22:08 931 */ 932public class HighlighterParam { 933 /**是否需要设置高亮*/ 934 private boolean highlight; 935 /**需要设置高亮的属性名*/ 936 private String fieldName; 937 /**高亮前缀*/ 938 private String prefix; 939 /**高亮后缀*/ 940 private String stuffix; 941 /**显示摘要最大长度*/ 942 private int fragmenterLength; 943 public boolean isHighlight() { 944 return highlight; 945 } 946 public void setHighlight(boolean highlight) { 947 this.highlight = highlight; 948 } 949 public String getFieldName() { 950 return fieldName; 951 } 952 public void setFieldName(String fieldName) { 953 this.fieldName = fieldName; 954 } 955 public String getPrefix() { 956 return prefix; 957 } 958 public void setPrefix(String prefix) { 959 this.prefix = prefix; 960 } 961 public String getStuffix() { 962 return stuffix; 963 } 964 public void setStuffix(String stuffix) { 965 this.stuffix = stuffix; 966 } 967 public int getFragmenterLength() { 968 return fragmenterLength; 969 } 970 public void setFragmenterLength(int fragmenterLength) { 971 this.fragmenterLength = fragmenterLength; 972 } 973 public HighlighterParam(boolean highlight, String fieldName, String prefix, String stuffix, int fragmenterLength) { 974 this.highlight = highlight; 975 this.fieldName = fieldName; 976 this.prefix = prefix; 977 this.stuffix = stuffix; 978 this.fragmenterLength = fragmenterLength; 979 } 980 981 public HighlighterParam(boolean highlight, String fieldName, int fragmenterLength) { 982 this.highlight = highlight; 983 this.fieldName = fieldName; 984 this.fragmenterLength = fragmenterLength; 985 } 986 987 public HighlighterParam(boolean highlight, String fieldName, String prefix, String stuffix) { 988 this.highlight = highlight; 989 this.fieldName = fieldName; 990 this.prefix = prefix; 991 this.stuffix = stuffix; 992 } 993 public HighlighterParam() { 994 } 995}
工具类对IndexWriter,IndexReader,IndexSearcher,Analyzer,QueryParser等Lucene这些常用操作对象的获取进行了封装,其中IndexWriter采用了单例模式,确保始终只有一个对象实例,因为Lucene限制了索引写操作是阻塞的,即同一时刻只能有一个IndexWriter在执行写操作,直到indexWriter释放lock,而索引读的操作是可以并发进行的。