通用dao public interface ForumuploadLuceneDao { public static final String FIELD_FORUMUPLOAD_ID="forumupload_id"; public static final String FIELD_TITLE = "title"; public static final String FIELD_SUMMARY = "summary"; public static final String FIELD_KEYWORDS = "keywords"; public static final String FIELD_REURL = "reurl"; //索引存放目录 // public static final String INDEX_DIR = Thread.currentThread().getContextClassLoader().getResource("").getPath()+ "index_dir"; public static final String INDEX_DIR = "C://Program Files//Apache Software Foundation"+ "//index_dir"; /** * 对所有上传文件进行重新索引 */ public void rebuildAllIndex(); /** * 对指定上传文件对象进行索引并追加到已有的索引文件中 * @param product */ public void doIndexSingle(Forumupload forumupload); /** * 根据关键字搜索,返回符合条件的分页数据 * @param keyword 关键字 * @param pageNo 起始页 * @param pageSize 每页要显示的记录数 * @return LuceneSearchResult对象 */ public LuceneSearchResult<Forumupload> doSeacher(String keyword, int pageNo, int pageSize); /** * 更新上传文件的索引 * @param product */ public void updateIndex(Forumupload forumupload); /** * 根据上传文件id删除索引 * @param id */ public void deleteIndex(Integer id); } 通用daoImp 实现 public class ForumuploadLuceneDaoImpl extends SqlMapClientDaoSupport implements ForumuploadLuceneDao { private ForumuploadDao forumuploadDao; public ForumuploadDao getForumuploadDao() { return forumuploadDao; } public void setForumuploadDao(ForumuploadDao forumuploadDao) { this.forumuploadDao = forumuploadDao; } public void setProductDao(ForumuploadDao forumuploadDao) { this.forumuploadDao = forumuploadDao; } /** 获取语法解析器 */ private Analyzer getAnalyzer() { //return new SmartChineseAnalyzer(Version.LUCENE_CURRENT); //return new PaodingAnalyzer(); return new StandardAnalyzer(Version.LUCENE_CURRENT); } /** 打开索引的存放目录 */ private Directory openDirectory(){ try { System.out.println(new File(INDEX_DIR)+"-------打开索引--------------"); return FSDirectory.open(new File(INDEX_DIR)); } catch (IOException e) { e.printStackTrace(); } return null; } /** 对上传文件的指定属性映射成域,返回上传文件文档对象 */ private Document createForumuploadDocument(Forumupload forumupload){ Document doc = new Document(); //创建一个文档对象 //id域 Field field = new Field(FIELD_FORUMUPLOAD_ID, String.valueOf(forumupload.getForumupload_id()), Field.Store.YES, Field.Index.NOT_ANALYZED); doc.add(field); //title域 Field field1 = new Field(FIELD_TITLE, String.valueOf(forumupload.getTitle()), Field.Store.YES, Field.Index.NOT_ANALYZED); doc.add(field1); //summary域 Field field2 = new Field(FIELD_SUMMARY, String.valueOf(forumupload.getSummary()), Field.Store.YES, Field.Index.ANALYZED); doc.add(field2); // keywords域 Field field3 = new Field(FIELD_KEYWORDS, String.valueOf(forumupload.getKeywords()), Field.Store.YES, Field.Index.ANALYZED); doc.add(field3); //reurl 域 Field field4 = new Field(FIELD_REURL, String.valueOf(forumupload.getReurl()), Field.Store.YES, Field.Index.ANALYZED); doc.add(field4); return doc; } /** * 对指定上传文件对象进行索引并追加到已有的索引文件中 * @param forumupload */ public synchronized void doIndexSingle(Forumupload forumupload){ //创建索引写入器 IndexWriter indexWriter = null; try { indexWriter = new IndexWriter(openDirectory(), getAnalyzer(), false, IndexWriter.MaxFieldLength.UNLIMITED); Document doc = this.createForumuploadDocument(forumupload); indexWriter.addDocument(doc); indexWriter.optimize(); //对索引进行优化 } catch (CorruptIndexException e) { e.printStackTrace(); } catch (LockObtainFailedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(indexWriter != null){ indexWriter.close(); //关闭IndexWriter,把内存中的数据写到文件 } } catch (CorruptIndexException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } /** * 根据关键字搜索,返回符合条件的分页数据 * @param queryString * @return */ public LuceneSearchResult<Forumupload> doSeacher(String keyword, int pageNo, int pageSize) { LuceneSearchResult<Forumupload> lsr = new LuceneSearchResult<Forumupload>(); lsr.setPageNo(pageNo); lsr.setPageSize(pageSize); lsr.setKeyword(keyword); IndexSearcher searcher = null; try{ //创建一个索引搜索器 searcher = new IndexSearcher(this.openDirectory(), true); //用多域查询解析器来创建一个查询器, Query query = MultiFieldQueryParser.parse(Version.LUCENE_CURRENT, keyword, new String[] { FIELD_TITLE,FIELD_SUMMARY,FIELD_KEYWORDS,FIELD_REURL}, new BooleanClause.Occur[]{ BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD, BooleanClause.Occur.SHOULD }, this.getAnalyzer()); long begin = System.currentTimeMillis(); //查询结集信息类 TopDocs ts = searcher.search(query, null, 100000); //获取命中的数量 lsr.setRecordCount(ts.totalHits); // 用这个进行高亮显示,默认是<b>..</b> SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<span style="/" mce_style="/""color:red/">", "</span>"); // 构造高亮:指定高亮的格式,指定查询评分 Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query)); highlighter.setTextFragmenter(new SimpleFragmenter(Integer.MAX_VALUE)); //获取匹配到的结果集 ScoreDoc[] hits = ts.scoreDocs; List<Forumupload> ais = new ArrayList<Forumupload>(); int pageCount = (lsr.getRecordCount() + pageSize - 1) / pageSize; //总页数 int start =0; //要开始返回的文档编号 int end = 0; //要结束返回的文档编号 if(pageCount > 0){ start = (pageNo - 1) * pageSize; end = start + pageSize; if(pageNo == pageCount){ //处理最后一页的结束文档的编号 end = start + (lsr.getRecordCount() % pageSize); } } if(start < end){ lsr.setStratNo(start + 1); lsr.setEndNo(end); } for (int i = start; i < end; i++) { //循环获取分页数据 //通过内部编号从搜索器中得到对应的文档 Document doc = searcher.doc(hits[i].doc); Forumupload forumupload = new Forumupload(); forumupload.setForumupload_id(Integer.valueOf(doc.getField(FIELD_FORUMUPLOAD_ID).stringValue())); forumupload.setTitle(doc.getField(FIELD_TITLE).stringValue()); forumupload.setSummary(doc.getField(FIELD_SUMMARY).stringValue()); forumupload.setKeywords(doc.getField(FIELD_KEYWORDS).stringValue()); forumupload.setReurl(doc.getField(FIELD_REURL).stringValue()); //后加 //处理上传文件名称的高亮显示问题 String name = doc.getField(FIELD_TITLE).stringValue(); String name2 = highlighter.getBestFragment(this.getAnalyzer(), FIELD_TITLE, name); if(name2 == null){ forumupload.setTitle(name); }else{ forumupload.setTitle(name2); } //上传文件描述高亮显示 String summary = doc.getField(FIELD_SUMMARY).stringValue(); String summary2 = highlighter.getBestFragment(this.getAnalyzer(), FIELD_SUMMARY, summary); if(summary2 == null ){ forumupload.setSummary(summary); }else { if(summary2.length() > 512){ forumupload.setSummary(summary2.substring(0, 512) + "..."); }else{ forumupload.setSummary(summary2); } } //对上传文件的关键字进行高亮显示 String keyword1 = doc.getField(FIELD_KEYWORDS).stringValue(); String keyword2 = highlighter.getBestFragment(this.getAnalyzer(), FIELD_KEYWORDS, keyword1); if(keyword2 == null ){ forumupload.setKeywords(keyword1); }else { if(keyword2.length() > 512){ forumupload.setKeywords(keyword2.substring(0, 512) + "..."); }else{ forumupload.setKeywords(keyword2); } } ais.add(forumupload); //把符合条件的数据添加到List } lsr.setTime((System.currentTimeMillis() - begin) / 1000.0); //计算搜索耗时秒数 lsr.setDatas(ais); //把查询到的数据添加到LuceneSearchResult } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } catch (InvalidTokenOffsetsException e) { e.printStackTrace(); } finally { if (searcher != null) { try { searcher.close(); //关闭搜索器 } catch (Exception e) { e.printStackTrace(); } } } return lsr; } /** * 对所有上传文件进行重新索引 */ public synchronized void rebuildAllIndex(){ File file = new File(INDEX_DIR); System.out.println("-------建立索引--------------------------"+INDEX_DIR); if(file.exists()){ for(File subFile : file.listFiles()){ subFile.delete(); } }else{ file.mkdirs(); } List<Forumupload> data = this.forumuploadDao.findAll(); IndexWriter indexWriter = null; try { indexWriter = new IndexWriter(this.openDirectory(), getAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); //设置打开使用复合文件 //indexWriter.setUseCompoundFile(true); int size = data == null ? 0 : data.size(); for (int i = 0; i < size; i++) { Forumupload forumupload = data.get(i); Document doc = createForumuploadDocument(forumupload); indexWriter.addDocument(doc); if(i % 20 == 0){ indexWriter.commit(); } } indexWriter.optimize(); //对索引进行优化 } catch (CorruptIndexException e) { e.printStackTrace(); } catch (LockObtainFailedException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(indexWriter != null){ indexWriter.close();//关闭IndexWriter,把内存中的数据写到文件 } } catch (CorruptIndexException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } public void deleteIndex(Integer id){ IndexReader ir = null; try { //打开指定目录下索引文件的索引读取器 ir = IndexReader.open(this.openDirectory(), false); //删除符合条件的Document ir.deleteDocuments(new Term(FIELD_FORUMUPLOAD_ID, String.valueOf(id))); } catch (IOException e) { e.printStackTrace(); }finally{ if(ir != null){ try { ir.close(); } catch (IOException e) { e.printStackTrace(); } } } } public void updateIndex(Forumupload forumupload){ this.deleteIndex(forumupload.getForumupload_id()); this.doIndexSingle(forumupload); } } 结果集 /** * Lucene搜索返回的结果 */ public class LuceneSearchResult<T> { private int pageNo = 1; //当前页 private int pageSize = 5; //每页显示记录数 private int recordCount; //总记录数 private double time; //耗时 private List<T> datas; //当前页的数据 private int stratNo; //开始记录数 private int endNo; //结束记录数 private String keyword; //关键字 public int getPageNo() { return pageNo; } public void setPageNo(int pageNo) { this.pageNo = pageNo; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getRecordCount() { return recordCount; } public void setRecordCount(int recordCount) { this.recordCount = recordCount; } public List<T> getDatas() { return datas; } public void setDatas(List<T> datas) { this.datas = datas; } public double getTime() { return time; } public void setTime(double time) { this.time = time; } public String getKeyword() { return keyword; } public void setKeyword(String keyword) { this.keyword = keyword; } public int getStratNo() { return stratNo; } public void setStratNo(int stratNo) { this.stratNo = stratNo; } public int getEndNo() { return endNo; } public void setEndNo(int endNo) { this.endNo = endNo; } } 测试 public class Test { /** * @param args */ public static void main(String[] args) { ApplicationContext context= new ClassPathXmlApplicationContext("classpath:config/spring/enterprise/applicationContext-*.xml"); ForumuploadLuceneService forumuploadLuceneService=(ForumuploadLuceneService)context.getBean("forumuploadLuceneService"); forumuploadLuceneService.rebuildForumuploadIndex(); // LuceneSearchResult<Forumupload> result =forumuploadLuceneService.doSeacher("ibatis", 1, 5); // // System.out.println("总共有:" + result.getRecordCount()); // System.out.println("关键字:" + result.getKeyword()); // System.out.println("总time:" + result.getTime()); // for(Forumupload prod : result.getDatas()){ // System.out.println( prod.getForumupload_id()+"----------id"); // System.out.println( prod.getTitle()+"----------title"); // System.out.println( prod.getSummary()+"----------summary"); // System.out.println( prod.getKeywords()+"----------keywords"); // System.out.println( prod.getReurl()+"----------reurl"); // System.out.println("---------------------------------------"); // } } } 建 立索引时需要从数据库中查找,所以建立索引的时会发送一条select 语句 <!-- 查询所有上传文件返回该类型的所有对象列表。否则返回null --> <select id="findAll" resultClass="forumupload" > <!--[CDATA[ select forumupload_id,title,summary,keywords,reurl from forumupload ]]--> </select> applicationContext-dao.xml <!-- 进行全文索引 --> <bean id="forumuploadLuceneDao" class="com.tongdainfo.dao.forumupload.lucene.ForumuploadLuceneDaoImpl"> <property name="sqlMapClient" ref="sqlMapClient"></property> <property name="forumuploadDao" ref="forumuploadDao"></property> </bean> applicationContext-service.xml <bean id="forumuploadLuceneService" class="com.tongdainfo.server.forumupload.lucene.ForumuploadLuceneServiceImpl"> <property name="forumuploadLuceneDao" ref="forumuploadLuceneDao"></property> </bean> applicationContext-action.xml <!-- 文件上传进行索引 --> <bean id="forumuploadLuceneAction" class="com.tongdainfo.action.forumupload.lucene.ForumuploadLuceneAction" > <property name="forumuploadLuceneService" ref="forumuploadLuceneService" ></property> </bean> 页面数据的展示 <table width="100%" height="92" border="0" cellpadding="0" cellspacing="1"> <div class="longTitle">搜索结果:搜索关键字【${lsr.keyword}】,共搜索到【${lsr.recordCount }】个文件,耗时:${lsr.time}秒,当前显示${lsr.stratNo}—${lsr.endNo}记录</div> <c:forEach items="${request.lsr.datas}" var="forumupload"> <tr> <td height="30" colspan="6" align="left" bgcolor="#f2f2f2" class="left_txt"> <a href="${base}/download/download.action?filename=${forumupload.reurl}" mce_href="${base}/download/download.action?filename=${forumupload.reurl}" > ${forumupload.title} </a> </td> <td height="30" colspan="6" align="left" bgcolor="#f2f2f2" class="left_txt">${forumupload.summary}</td> </tr> </c:forEach> </table>