Lucene系列:LuceneUtils之同步分页
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Lucene系列:LuceneUtils之同步分页相关的知识,希望对你有一定的参考价值。
1、工具类LuceneUtils
LuceneUtils.java
package com.rk.lucene.utils; import java.io.File; import java.io.IOException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import org.apache.commons.beanutils.BeanUtils; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.Field.Index; import org.apache.lucene.document.Field.Store; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.index.IndexWriter.MaxFieldLength; import org.apache.lucene.queryParser.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; import org.junit.Test; import com.rk.lucene.entity.Article; import com.rk.lucene.entity.Page; public class LuceneUtils { private static Directory directory; private static Version version; private static Analyzer analyzer; private static MaxFieldLength maxFieldLength; private static final String LUCENE_DIRECTORY= "D:/rk/indexDB"; static{ try { directory = FSDirectory.open(new File(LUCENE_DIRECTORY)); version = Version.LUCENE_30; analyzer = new StandardAnalyzer(version); maxFieldLength = MaxFieldLength.LIMITED; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } //不让外部new当前帮助类的对象 private LuceneUtils(){} public static <T> void pagination(Page<T> page,String field,String keyword,Class<T> clazz) throws Exception{ QueryParser queryParser = new QueryParser(getVersion(), field, getAnalyzer()); Query query = queryParser.parse(keyword); IndexSearcher indexSearcher = new IndexSearcher(getDirectory()); TopDocs topDocs = indexSearcher.search(query, 200); int totalHits = topDocs.totalHits; int curPage = page.getCurPage(); int pageSize = page.getPageSize(); int quotient = totalHits / pageSize; int remainder = totalHits % pageSize; int totalPages = remainder==0 ? quotient : quotient+1; int startIndex = (curPage-1) * pageSize; int stopIndex = Math.min(startIndex + pageSize, totalHits); List<T> list = page.getItems(); if(list == null){ list = new ArrayList<T>(); page.setItems(list); } list.clear(); for(int i=startIndex;i<stopIndex;i++){ ScoreDoc scoreDoc = topDocs.scoreDocs[i]; int docIndex = scoreDoc.doc; Document document = indexSearcher.doc(docIndex); T t = document2javabean(document, clazz); list.add(t); } page.setTotalPages(totalPages); page.setTotalItems(totalHits); indexSearcher.close(); } public static <T> void add(T t) throws Exception{ Document document = javabean2document(t); IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength()); indexWriter.addDocument(document); indexWriter.close(); } public static <T> void addAll(List<T> list) throws Exception{ IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength()); for(T t : list){ Document doc = javabean2document(t); indexWriter.addDocument(doc); } indexWriter.close(); } public static <T> void update(String field,String value,T t) throws Exception{ Document document = javabean2document(t); IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength()); indexWriter.updateDocument(new Term(field,value), document); indexWriter.close(); } public static <T> void delete(String field,String value) throws Exception{ IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength()); indexWriter.deleteDocuments(new Term(field,value)); indexWriter.close(); } /** * 删除所有记录 */ public static void deleteAll() throws Exception { IndexWriter indexWriter = new IndexWriter(getDirectory(), getAnalyzer(), getMaxFieldLength()); indexWriter.deleteAll(); indexWriter.close(); } /** * 根据关键字进行搜索 */ public static <T> List<T> search(String field,String keyword,int topN) throws Exception{ List<T> list = new ArrayList<T>(); QueryParser queryParser = new QueryParser(getVersion(), field, getAnalyzer()); Query query = queryParser.parse(keyword); IndexSearcher indexSearcher = new IndexSearcher(getDirectory()); TopDocs topDocs = indexSearcher.search(query, topN); for(int i=0;i<topDocs.scoreDocs.length;i++){ ScoreDoc scoreDoc = topDocs.scoreDocs[i]; int docIndex = scoreDoc.doc; System.out.println("文档索引号" + docIndex + ",文档得分:" + scoreDoc.score); Document document = indexSearcher.doc(docIndex); T entity = (T) document2javabean(document, Article.class); list.add(entity); } indexSearcher.close(); return list; } /** * 打印List */ public static <T> void printList(List<T> list){ if(list != null && list.size()>0){ for(T t : list){ System.out.println(t); } } } //将JavaBean转成Document对象 public static Document javabean2document(Object obj) throws Exception{ //创建Document对象 Document document = new Document(); //获取obj引用的对象字节码 Class clazz = obj.getClass(); //通过对象字节码获取私有的属性 java.lang.reflect.Field[] reflectFields = clazz.getDeclaredFields(); //迭代 for(java.lang.reflect.Field reflectField : reflectFields){ //反射 reflectField.setAccessible(true); //获取字段名 String name = reflectField.getName(); //获取字段值 String value = reflectField.get(obj).toString(); //加入到Document对象中去,这时javabean的属性与document对象的属性相同 document.add(new Field(name, value, Store.YES, Index.ANALYZED)); } //返回document对象 return document; } //将Document对象转换成JavaBean对象 public static <T> T document2javabean(Document document,Class<T> clazz) throws Exception{ T obj = clazz.newInstance(); java.lang.reflect.Field[] reflectFields = clazz.getDeclaredFields(); for(java.lang.reflect.Field reflectField : reflectFields){ reflectField.setAccessible(true); String name = reflectField.getName(); String value = document.get(name); BeanUtils.setProperty(obj, name, value); } return obj; } public static Directory getDirectory() { return directory; } public static void setDirectory(Directory directory) { LuceneUtils.directory = directory; } public static Version getVersion() { return version; } public static void setVersion(Version version) { LuceneUtils.version = version; } public static Analyzer getAnalyzer() { return analyzer; } public static void setAnalyzer(Analyzer analyzer) { LuceneUtils.analyzer = analyzer; } public static MaxFieldLength getMaxFieldLength() { return maxFieldLength; } public static void setMaxFieldLength(MaxFieldLength maxFieldLength) { LuceneUtils.maxFieldLength = maxFieldLength; } //测试 public static void main(String[] args) throws Exception { Article article = new Article(1, "你好", "欢迎来到我的世界"); Document document = javabean2document(article); Article a2 = (Article) document2javabean(document, Article.class); System.out.println(a2); } }
2、entity->dao->service->action
Article.java
package com.rk.lucene.entity; public class Article { private Integer id; private String title;//标题 private String content;//内容 public Article() { } public Article(Integer id, String title, String content) { this.id = id; this.title = title; this.content = content; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "Article [编号=" + id + ", 标题=" + title + ", 内容=" + content + "]"; } }
ArticleDao.java
package com.rk.lucene.dao; import com.rk.lucene.entity.Article; import com.rk.lucene.entity.Page; import com.rk.lucene.utils.LuceneUtils; public class ArticleDao { public void pagination(Page<Article> page,String keyword) throws Exception{ LuceneUtils.pagination(page, "content", keyword, Article.class); } }
ArticleService.java
package com.rk.lucene.service; import com.rk.lucene.dao.ArticleDao; import com.rk.lucene.entity.Article; import com.rk.lucene.entity.Page; public class ArticleService { private ArticleDao dao = new ArticleDao(); public Page<Article> pagination(String keyword,int curPage,int pageSize) throws Exception { Page<Article> page = new Page<Article>(); page.setCurPage(curPage); page.setPageSize(pageSize); dao.pagination(page, keyword); return page; } }
ArticleServlet.java
package com.rk.lucene.action; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.rk.lucene.entity.Article; import com.rk.lucene.entity.Page; import com.rk.lucene.service.ArticleService; public class ArticleServlet extends HttpServlet{ @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { request.setCharacterEncoding("UTF-8"); //获取关键字(此处并不完善,没有对关键字的有效性进行校验) String keyword = request.getParameter("keyword"); String strPageNo = request.getParameter("pageNo"); //只有当页码真实存在时,才进行查询 if(strPageNo != null && !"".equals(strPageNo)){ int curPage = Integer.parseInt(strPageNo); //调用业务层 ArticleService service = new ArticleService(); Page<Article> page = service.pagination(keyword, curPage, 2); //将Page对象绑定到request域对象中 request.setAttribute("PAGE", page); } //将keywords变量绑定到request域对象中 request.setAttribute("KEYWORD", keyword); //转发到list.jsp页面 request.getRequestDispatcher("/index.jsp").forward(request, response); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } }
在web.xml中注册ArticleServlet
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>lucene01</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>ArticleServlet</servlet-name> <servlet-class>com.rk.lucene.action.ArticleServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>ArticleServlet</servlet-name> <url-pattern>/article</url-pattern> </servlet-mapping> </web-app>
3、前台index.jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>同步分页</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <!-- 输入区 --> <form action="${pageContext.request.contextPath}/article" method="post"> <input type="hidden" name="pageNo"/> <table border="1" align="center" style="border-collapse:collapse;"> <tr> <th>输入关键字</th> <td><input type="text" name="keyword" value="${requestScope.KEYWORD}" maxlength="10"/> </td> <td><input id="search" type="button" value="站内搜索"/> </td> </tr> </table> <script type="text/javascript"> //去空格 function trim(str){ //先去左边的空格 str = str.replace(/^s*/, ""); //后去右边的空格 str = str.replace(/\s*$/, ""); //返回 return str; } //定位“站内搜索”按钮,同时提供单击事件 document.getElementById("search").onclick = function(){ //定位表单 var formElement = document.forms[0]; //获取关键字 var keyword = formElement.keyword.value; //去空格 keyword = trim(keyword); //判断长度 if(keyword.length == 0){ //提示 alert("你没有填写关键字"); } else{ //提交表单 formElement.pageNo.value = 1; formElement.submit(); } }; </script> </form> <c:if test="${not empty requestScope.PAGE }"> <!-- 显示区 --> <table border="2" align="center" width="70%" style="border-collapse:collapse;"> <tr> <th>编号</th> <th>标题</th> <th>内容</th> </tr> <c:forEach var="article" items="${requestScope.PAGE.items}"> <tr> <td>${article.id}</td> <td>${article.title}</td> <td>${article.content }</td> </tr> </c:forEach> <tr> <th colspan="3" align="center"> <c:choose> <c:when test="${requestScope.PAGE.curPage <= 1 }"> 首页 </c:when> <c:otherwise> <a onclick="fy(1)" style="cursor:hand;color:blue;text-decoration:underline;">首页</a> </c:otherwise> </c:choose> <c:choose> <c:when test="${requestScope.PAGE.curPage <= 1 }"> 上一页 </c:when> <c:otherwise> <a onclick="fy(${requestScope.PAGE.curPage-1})" style="cursor:hand;color:blue;text-decoration:underline;">上一页</a> </c:otherwise> </c:choose> <c:choose> <c:when test="${requestScope.PAGE.curPage >= requestScope.PAGE.totalPages }"> 下一页 </c:when> <c:otherwise> <a onclick="fy(${requestScope.PAGE.curPage+1})" style="cursor:hand;color:blue;text-decoration:underline;">下一页</a> </c:otherwise> </c:choose> <c:choose> <c:when test="${requestScope.PAGE.curPage >= requestScope.PAGE.totalPages }"> 末页 </c:when> <c:otherwise> <a onclick="fy(${requestScope.PAGE.totalPages})" style="cursor:hand;color:blue;text-decoration:underline;">末页</a> </c:otherwise> </c:choose> 共${requestScope.PAGE.totalPages}页,当前第${requestScope.PAGE.curPage}页 </th> </tr> </table> <script type="text/javascript"> function fy(curPage){ //定位表单 var formElement = document.forms[0]; //修改当前页号 formElement.pageNo.value = curPage; //提交表单 formElement.submit(); } </script> </c:if> </body> </html>
遇到的一个问题 |
Exception in thread "main" org.apache.lucene.queryParser.ParseException: Encountered "<EOF>" at line 1, column 0. 可能是代码写错了。 错误的代码: Query query = queryParser.Query(keyword); 正确的代码: Query query = queryParser.parse(keyword); |
以上是关于Lucene系列:LuceneUtils之同步分页的主要内容,如果未能解决你的问题,请参考以下文章