标签:lucene
| 使用到的jar包,分为4部分: |
(1)beanutils commons-beanutils-1.9.2.jar commons-collections-3.2.1.jar commons-logging-1.1.1.jar (2)gson gson-2.6.2.jar (3)IK Analyzer IKAnalyzer3.2.0Stable.jar (4)lucene lucene-analyzers-3.0.2.jar lucene-core-3.0.2.jar lucene-highlighter-3.0.2.jar lucene-memory-3.0.2.jar |
1、LuceneUtils
LuceneUtils.java
package com.rk.lucene.utils;
import java.io.File;
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.MultiFieldQueryParser;
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.Formatter;
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.Scorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;
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);
analyzer = new IKAnalyzer();
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 paginationWithHighlighter(Page<T> page,String keyword,Class<T> clazz) throws Exception{
QueryParser queryParser = new MultiFieldQueryParser(getVersion(), new String[]{"title","content"}, analyzer);
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();
Formatter formatter = new SimpleHTMLFormatter("<font color=‘red‘>", "</font>");
Scorer scorer = new QueryScorer(query);
Highlighter titleHighlighter = new Highlighter(formatter, scorer);
Highlighter contentHighlighter = new Highlighter(formatter, scorer);
int MAX_CONTENT_LENGTH = 30;
Fragmenter contentFragmenter = new SimpleFragmenter(MAX_CONTENT_LENGTH);
contentHighlighter.setTextFragmenter(contentFragmenter);
for(int i=startIndex;i<stopIndex;i++){
ScoreDoc scoreDoc = topDocs.scoreDocs[i];
int docIndex = scoreDoc.doc;
Document document = indexSearcher.doc(docIndex);
String titleValue = titleHighlighter.getBestFragment(LuceneUtils.getAnalyzer(), "title", document.get("title"));
if(titleValue == null) titleValue = document.get("title");
String contentValue = contentHighlighter.getBestFragment(LuceneUtils.getAnalyzer(), "content", document.get("content"));
if(contentValue == null) contentValue = document.get("content").substring(0, MAX_CONTENT_LENGTH);
document.getField("title").setValue(titleValue);
document.getField("content").setValue(contentValue);
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,Class<T> clazz) 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, clazz);
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;
}
}Page.java
package com.rk.lucene.entity;
import java.util.ArrayList;
import java.util.List;
public class Page<T> {
private Integer totalItems;
private Integer totalPages;
private Integer pageSize;
private Integer curPage;
private List<T> items = new ArrayList<T>();
public Page() {
}
public Integer getTotalItems() {
return totalItems;
}
public void setTotalItems(Integer totalItems) {
this.totalItems = totalItems;
}
public Integer getTotalPages() {
return totalPages;
}
public void setTotalPages(Integer totalPages) {
this.totalPages = totalPages;
}
public Integer getPageSize() {
return pageSize;
}
public void setPageSize(Integer pageSize) {
this.pageSize = pageSize;
}
public Integer getCurPage() {
return curPage;
}
public void setCurPage(Integer curPage) {
this.curPage = curPage;
}
public List<T> getItems() {
return items;
}
public void setItems(List<T> items) {
this.items = items;
}
}准备测试数据
package com.rk.lucene.g_search;
import java.util.ArrayList;
import java.util.List;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
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.junit.Test;
import com.rk.lucene.entity.Article;
import com.rk.lucene.utils.LuceneUtils;
public class PrepareData {
@Test
public void testAdd() throws Exception{
List<Article> list = new ArrayList<Article>();
list.add(new Article(1, "疾风之刃", "《疾风之刃》是一款超动作3D动漫风网游。作为新一代动作游戏,《疾风之刃》呈现出极致华丽的动作表演,精心打磨出的打击感震撼人心。"));
list.add(new Article(2, "月光疾风", "月光疾风,日本动漫《火影忍者》中的人物,比较个人主义,性格温和。火之国木叶村的特别上忍,中忍考试正赛预选的考官,体质似乎很不好,有着严重的黑眼圈、脸色苍白且经常咳嗽,善用剑术。"));
list.add(new Article(3, "疾风航班中文版下载", "《疾风航班》是一款优质的动作模拟游戏。游戏中包括亚欧美洲,乃至飞往太空的5条航线,共计50个循序渐进的关卡,以及具有挑战性的Expert级别评定,每个关卡结束后还可进入商店对主角和飞机进..."));
list.add(new Article(4, "八神疾风", "八神疾风(CV:植田佳奈)是日本动漫《魔法少女奈叶A‘s》首次登场的女角色。暗之书事件中心人物,时空管理局魔导师,擅长贝尔卡式广域·远程魔法。"));
list.add(new Article(5, "逝去的疾风", "大战中飞得最快的日本飞机,恐怕要数“疾风”战斗机了,它由中岛飞机厂研制生产,制式型号为: 四式单(座)战(斗机),代号キ-84(读作 Ki-84)。"));
list.add(new Article(6, "疾风剑豪 亚索", "亚索是一个百折不屈的男人,还是一名身手敏捷的剑客,能够运用风的力量来斩杀敌人。这位曾经春风得意的战士因为诬告而身败名裂,并且被迫卷入了一场令人绝望的生存之..."));
list.add(new Article(7, "疾风知劲草", "疾风知劲草,谓在猛烈的大风中,可看出什么样的草是强劲的。比喻意志坚定,经得起考验。出自《东观汉记·王霸传》:“上谓霸曰:‘颍川从我者皆逝,而子独留,始验疾风知劲草。..."));
LuceneUtils.addAll(list);
}
}2、entity->dao->service->action
2.1、entity层
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 "编号: " + id + "\n标题: " + title + "\n内容: " + content +
"\n------------------------------------------------------------------\n";
}
}2.2、dao层
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.paginationWithHighlighter(page, 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 java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
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 {
Map<String,Object> map = new HashMap<String, Object>();
try {
request.setCharacterEncoding("UTF-8");
//获取关键字
String keyword = request.getParameter("keyword");
String strPageNo = request.getParameter("page");
String strRows = request.getParameter("rows");
//只有当页码真实存在时,才进行查询
if(keyword != null && keyword.length()>0){
int curPage = Integer.parseInt(strPageNo);
int rows = Integer.parseInt(strRows);
//调用业务层
ArticleService service = new ArticleService();
Page<Article> page = service.pagination(keyword, curPage, rows);
map.put("total", page.getTotalItems());
map.put("rows", page.getItems());
}
else{
map.put("total", 0);
map.put("rows", "[]");
}
//以IO的流方式响应到DataGrid组件
Gson gson = new GsonBuilder().create();
String strJson = gson.toJson(map);
response.setContentType("application/json;charset=UTF-8");
PrintWriter pw = response.getWriter();
pw.write(strJson);
pw.flush();
pw.close();
} 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>lucene02</display-name> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <servlet> <servlet-name>article</servlet-name> <servlet-class>com.rk.lucene.action.ArticleServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>article</servlet-name> <url-pattern>/article</url-pattern> </servlet-mapping> </web-app>
3、前台JSP
在页面当中使用到了jQuery easyUI
将标注的文件和文件夹引入到Web项目中
index.jsp
<%@ page language="java" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>使用Jsp +Js + Jquery + EasyUI + Servlet + Lucene,完成分页</title>
<!-- 引入css文件,无顺序 -->
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/easyui/themes/icon.css"></link>
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/easyui/themes/default/easyui.css"></link>
<!-- 引入js文件,有顺序 -->
<script type="text/javascript" src="${pageContext.request.contextPath}/js/easyui/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/easyui/locale/easyui-lang-zh_CN.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(‘#dg‘).datagrid({
url:"${pageContext.request.contextPath}/article?time="+new Date().getTime(),
columns:[[
{field:‘id‘,title:‘编号‘,width:30},
{field:‘title‘,title:‘标题‘,width:100},
{field:‘content‘,title:‘内容‘,width:100}
]],
fitColumns:true,
singleSelect:true,
pagination:true,
pageSize:2,
pageList:[2,4]
});
//定位“站内搜索”按钮
$(‘#btnSearch‘).click(function(){
//获取关键字
var keyword = $(‘#keyword‘).val();
//去空格
keyword = $.trim(keyword);
if(keyword.length == 0){
//提示
alert("请输入关键字!!!");
//清空文本框的内容
$(‘#keyword‘).val("");
//定位于输入关键字文本框
$(‘#keyword‘).focus();
}
else{
//异步发送请求到服务器
//load表示方法名
//"keyword"表示需要发送的的参数名,后台收:request.getParameter("keyword")
//keyword表示参数值
$(‘#dg‘).datagrid("load", {
"keyword":keyword
});
}
});
});
</script>
</head>
<body>
<!-- 输入区 -->
<form id="myFormId">
输入关键字:
<input id="keyword" type="text" value=""/>
<input id="btnSearch" type="button" value="站内搜索"/>
</form>
<!-- 显示区 -->
<table id="dg"></table>
</body>
</html>标签:lucene
原文地址:http://lsieun.blog.51cto.com/9210464/1852890