【Lucene】使用EasyUI和JQuery配合Lucene实现数据的分页查询以及高亮显示

在这里我们需要使用第三方工具将集合转换为JSON,以及用到组件BeanUtils,所以我们需要导入相应的jar包


然后导入JQuery和EasyUI相关js文件



并将EasyUI中的themes文件夹拷到WebRoot

包的结构图如下:


然后我们创建一个实体类Student

package cn.qblank.entity;

public class Student {
	private Integer id;
	private String name;
	private String describe;
	
	public Student(){}
	public Student(Integer id, String name, String describe) {
		super();
		this.id = id;
		this.name = name;
		this.describe = describe;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getDescribe() {
		return describe;
	}
	public void setDescribe(String destcribe) {
		this.describe = destcribe;
	}
	
	@Override
	public String toString() {
		return "编号:" + id + "\n" + "姓名:" + name +"\n" + "简历:" + describe;
	}
}

然后我们创建Page类,用于存储页面的属性:当前页面、每页显示记录数、总记录数、总页数

package cn.qblank.entity;

import java.util.ArrayList;
import java.util.List;

public class Page {
	private Integer currPageNO;//当前页号  
	private Integer perPageSize = 2;//每页显示记录数,默认为2条
	private Integer allRecordNO;//总记录数
	private Integer allPageNO;//总页数
	private List<Student> studentList = new ArrayList<Student>();//内容
	public Page(){}
	public Integer getCurrPageNO() {
		return currPageNO;
	}
	public void setCurrPageNO(Integer currPageNO) {
		this.currPageNO = currPageNO;
	}
	public Integer getPerPageSize() {
		return perPageSize;
	}
	public void setPerPageSize(Integer perPageSize) {
		this.perPageSize = perPageSize;
	}
	public Integer getAllRecordNO() {
		return allRecordNO;
	}
	public void setAllRecordNO(Integer allRecordNO) {
		this.allRecordNO = allRecordNO;
	}
	public Integer getAllPageNO() {
		return allPageNO;
	}
	public void setAllPageNO(Integer allPageNO) {
		this.allPageNO = allPageNO;
	}
	public List<Student> getStudentList() {
		return studentList;
	}
	public void setStudentList(List<Student> studentList) {
		this.studentList = studentList;
	}
	
}

写好工具类LuceneUtil

package cn.qblank.util;

import java.io.File;
import java.lang.reflect.Method;

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.MaxFieldLength;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

/**
 * Lucene工具类
 * @author Administrator
 *
 */
public class LuceneUtil {
	private static Directory directory ;
	private static Analyzer analyzer ; 
	private static Version version; 
	private static MaxFieldLength maxFieldLength;
	
	static{
		try {
			directory = FSDirectory.open(new File("F:/LuceneDB"));
			version = Version.LUCENE_30;
			analyzer = new StandardAnalyzer(version);
//			analyzer = new IKAnalyzer();
			maxFieldLength = MaxFieldLength.LIMITED;
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * javabean转document
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	public static Document javabean2documemt(Object obj) throws Exception{
		//创建document对象
		Document document = new Document();
		//获取字节码对象
		Class clazz = obj.getClass();
		//获取该对象中的私有属性: 使用强反射  这里使用类全称,防止和Lucene包起冲突
		java.lang.reflect.Field[] reflectfields = clazz.getDeclaredFields();
		
		//遍历字段
		for (java.lang.reflect.Field field : reflectfields) {
			//设置访问权限:因为字段是私有的
			field.setAccessible(true);
			String fieldName = field.getName();
			//给其拼装成get方法
			String methodName = "get" + fieldName.substring(0,1).toUpperCase() + fieldName.substring(1);
			
			Method method = clazz.getMethod(methodName, null);
			//调用方法
			String returnValue = method.invoke(obj, null).toString();
			
			document.add(new Field(fieldName, returnValue, Store.YES, Index.ANALYZED));
		}
		return document;
	}
	
	/**
	 * document转javabean,可以使用BeanUtils组件
	 * @throws Exception
	 */
	public static Object document2javabean(Document document,Class clazz) throws Exception{
		//先获取字节码对象
		Object obj = clazz.newInstance();
		//获取到各个字段名
		java.lang.reflect.Field[] reflectField = clazz.getDeclaredFields();
		for (java.lang.reflect.Field field : reflectField) {
			//设置访问权限
			field.setAccessible(true);
			//获取各个的字段名和值
			String fieldName = field.getName();
			String fieldValue = document.get(fieldName);
			//使用BeanUtils组件封装对象
			BeanUtils.setProperty(obj, fieldName, fieldValue);
		}
		return obj;
	}
	
	
	public static Directory getDirectory() {
		return directory;
	}
	public static Analyzer getAnalyzer() {
		return analyzer;
	}
	public static Version getVersion() {
		return version;
	}
	public static MaxFieldLength getMaxFieldLength() {
		return maxFieldLength;
	}
	
}

接下来我们创建StudentDao类查询Lucene的记录

package cn.qblank.dao;

import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.document.Document;
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.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;

import cn.qblank.entity.Student;
import cn.qblank.util.LuceneUtil;

/**
 * 持久层
 * @author Administrator
 *
 */
public class StudentDao {
	/**
	 * 根据关键字,获取总记录数
	 * @return 总记录数
	 */
	public int getAllRecord(String keywords) throws Exception{
		//创建查询器
		QueryParser queryParser = new QueryParser(LuceneUtil.getVersion(), "describe", LuceneUtil.getAnalyzer());
		//封装查询数据
		Query query = queryParser.parse(keywords);
		IndexSearcher indexSearcher = new IndexSearcher(LuceneUtil.getDirectory());
		TopDocs topDocs = indexSearcher.search(query, 2);
		
		indexSearcher.close();
		//返回符合条件的真实总记录数,不受2的影响
		return topDocs.totalHits;
		//返回符合条件的总记录数,受2的影响
		//return topDocs.scoreDocs.length;
	}
	
	/**
	 * 根据关键字,批量查询记录
	 * @param start 从第几条记录的索引号开始查询,索引号从0开始
	 * @param size  最多查询几条记录,不满足最多数目时,以实际为准
	 * @return 集合
	 */
	public List<Student> findAll(String keywords,int start,int size) throws Exception{
		//用于存储数据
		List<Student> studentList = new ArrayList<Student>();
		//创建查询器QuertParser
		QueryParser queryParser = new QueryParser(LuceneUtil.getVersion(), "describe", LuceneUtil.getAnalyzer());
		//封装查询数据
		Query query = queryParser.parse(keywords);
		IndexSearcher indexSearcher = new IndexSearcher(LuceneUtil.getDirectory());
		//查询前100条数据
		TopDocs topDocs = indexSearcher.search(query, 100);
		
		//将查询的结果高亮显示 
		//创建格式对象
		SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");
		//创建关键字对象
		QueryScorer scorer = new QueryScorer(query);
		//创建高亮对象
		Highlighter highlighter = new Highlighter(formatter, scorer);
		//代表显示的字的个数
		/*Fragmenter fragmenter = new SimpleFragmenter(4);
		highlighter.setTextFragmenter(fragmenter);*/
		//进行分页
		//获取查询的页数
		int middle = Math.min(start + size, topDocs.totalHits);
		for (int i = start; i < middle; i++) {
			ScoreDoc scoreDoc = topDocs.scoreDocs[i];
			//获取编号
			int no = scoreDoc.doc;
			//查询编号对应的document对象
			Document document = indexSearcher.doc(no);
			
			//高亮显示
			//关键字高亮显示
			String highlighterDescribe = highlighter.getBestFragment(LuceneUtil.getAnalyzer(), "describe",document.get("describe"));
			//String highlighterName = highlighter.getBestFragment(LuceneUtil.getAnalyzer(), "name",document.get("name"));
			//将标题和内容高亮
			document.getField("describe").setValue(highlighterDescribe);
			//document.getField("name").setValue(highlighterName);
			//将document对象转换为javabean
			Student student = (Student) LuceneUtil.document2javabean(document, Student.class);
			//将查询出来的数据添加到集合中
			studentList.add(student);
		}
		indexSearcher.close();
		return studentList;
	}
}

然后写好StudentService将查询到的数据进行逻辑判断,并将相应的数据封装到Page对象中

package cn.qblank.service;

import java.util.List;

import cn.qblank.dao.StudentDao;
import cn.qblank.entity.Page;
import cn.qblank.entity.Student;

/**
 * 业务层
 * @author Administrator
 *
 */
public class StudentService {
	private StudentDao studentDao = new StudentDao();
	/**
	 * 通过关键字查询内容
	 * @param keywords  关键字
	 * @param currPageNO 当前页号
	 * @throws Exception
	 */
	public Page show(String keywords,int currPageNO) throws Exception{
		Page page = new Page();
		
		//封装当前页号
		page.setCurrPageNO(currPageNO);
		//封装总记录数
		int allRecordNO = studentDao.getAllRecord(keywords);
		page.setAllRecordNO(allRecordNO);
		
		//封装总页数
		int allPageNO = 0;
		if (page.getAllRecordNO() % page.getPerPageSize() == 0) {
			allPageNO = page.getAllRecordNO() / page.getPerPageSize();
		}else{
			allPageNO = page.getAllRecordNO() % page.getPerPageSize() + 1;
		}
		//封装总页数
		page.setAllPageNO(allPageNO);
		//封装内容
		Integer size = page.getPerPageSize();
		Integer start = (page.getCurrPageNO() -1 ) * size;
		List<Student> studentList = studentDao.findAll(keywords, start, size);
		page.setStudentList(studentList);
		
		return page;
	}
}

然后写好EasyUI优化过的list.jsp的页面,然后将输入的关键字异步方式传入到后台

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>使用Jsp +Js + JQuery + EasyUI + Servlet + Lucene完成分页</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
	<!-- 导入css文件 -->
	<link rel="stylesheet" href="themes/icon.css" type="text/css"></link>
    <link rel="stylesheet" href="themes/default/easyui.css" type="text/css"></link>
	
	<!-- 导入js文件 按顺序导入 -->
	<script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" src="js/jquery.easyui.min.js"></script>
	<script type="text/javascript" src="js/easyui-lang-zh_CN.js"></script>
  </head>
  <body>
		<form id="myformID">
			输入关键字:<input type="text" value="" id="keywordID"/>
			<input type="button" value="站内搜索" id="findID"/>
		</form>
		<!-- 显示数据 -->
		<table id="dg"></table>
  </body>
  <script type="text/javascript">
  		//获取标签按钮
  		$("#findID").click(function(){
  			//获取输入框的内容
  			var keyword = $("#keywordID").val();
  			//去除空格
  			keyword = $.trim(keyword);
  			//为空判断
  			if (keyword.length == 0) {
				//提示
				alert("请输入内容");
				//清空文本内容
				$("#keywordID").val("");
				//定位输入框
				$("#keywordID").focus();
			}else{
				//异步发送到服务器中
				$("#dg").datagrid("load",
				{
					"keywords":keyword	
				});
			}
  		});
  </script>
  
  <!-- 显示数据代码 -->
  <script type="text/javascript">
  		$("#dg").datagrid({
  			/*  
				pagination 表示分页栏  默认为false
				pageSize 表示每个显示多少条记录
				pageList 表示可供选择的条数
				data-options 是easyui特有的属性
				url 表示加载json的路径
				fitColumns=true 表示等分宽度,要配合width:100这个属性值(提倡)
				fitColumns=false 表示不等分宽度,这时由width:100这个属性值来决定宽度,默认为false
				singleSelect=true 表示可以选择表格中的一项
				singleSelect=false 表示可以选择表格中的多项,默认为false
			*/
  			url:"${pageContext.request.contextPath}/StudentServlet?time=" + new Date().getTime(),
  			columns: 
  					[[
  						{field:"id",title:"编号",width:100},
  						{field:"name",title:"姓名",width:100},
  						{field:"describe",title:"描述",width:100}
  					]],
  			fitColumns:true,
  			singleSelect:false,
  			pageSize:2,
  			pageList:[2,4],
  			pagination:true
  		});
  </script>
</html>

然后后台StudentServlet处理list.jsp的数据

package cn.qblank.action;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;
import cn.qblank.entity.Page;
import cn.qblank.service.StudentService;

@SuppressWarnings("serial")
public class StudentServlet extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		this.doPost(req, resp);
	}
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		resp.setContentType("text/html;charset=utf-8");
		try {
			//获取关键字
			String keywords = req.getParameter("keywords");
			//如果为空,给默认值  好
			if (keywords == null || keywords.trim().length() == 0) {
				keywords = "好";
			}
			//获取当前页号  EasyUI固定写法获取页号
			String currPage = req.getParameter("page");
			if (currPage == null || currPage.trim().length() == 0) {
				currPage = "1";
			}
			//调用Service
			StudentService studentService = new StudentService();
			Page page = studentService.show(keywords, Integer.parseInt(currPage));
			
			//构造Map对象
			Map<String, Object> map = new LinkedHashMap<>();
			//将总页数和查询的结果列表存入Map集合中
			map.put("total", page.getAllRecordNO());
			map.put("rows", page.getStudentList());
			
			//将集合转为JSON对象
			JSONArray jsonArray = JSONArray.fromObject(map);
			//转换为java的字符串格式
			String jsonJAVA = jsonArray.toString();
			//去掉俩边的[]
			jsonJAVA = jsonJAVA.substring(1,jsonJAVA.length() - 1);
			//使用O流打印出去
			PrintWriter pw = resp.getWriter();
			pw.write(jsonJAVA);
			pw.flush();
			pw.close();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

事先我已经放入5调数据到Lucene库中,添加的代码可以看我的上篇博客

http://blog.csdn.net/evan_qb/article/details/78512216

接下来我们运行下,看下结果











  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值