一、版本依赖
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> </dependency> <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-api</artifactId> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-web</artifactId> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-to-slf4j</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> </dependency>
二、插件
import com.alibaba.fastjson.JSON;
import com.jfinal.kit.LogKit;
import com.jfinal.plugin.IPlugin;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.List;
/**
* elasticsearch 插件
* @author linkzz
* @create 2018-01-02 16:22
*/
public class ElasticSearchPlugin implements IPlugin {
private String ip;
private int port;
private String clusterName;
private static TransportClient client;
public ElasticSearchPlugin(String ip,int port,String clusterName){
this.ip = ip;
this.port = port;
this.clusterName = clusterName;
}
public static TransportClient getClient() {
return client;
}
@Override
public boolean start() {
Settings settings = Settings.builder()
//设置ES实例的名称
.put("cluster.name", this.clusterName)
//自动嗅探整个集群的状态,把集群中其他ES节点的ip添加到本地的客户端列表中
.put("client.transport.sniff", true)
.build();
/**
* 这里的连接方式指的是没有安装x-pack插件,如果安装了x-pack则参考{@link ElasticsearchXPackClient}
* 1. java客户端的方式是以tcp协议在9300端口上进行通信
* 2. http客户端的方式是以http协议在9200端口上进行通信
*/
try {
client = new PreBuiltTransportClient(settings).addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(this.ip), this.port));
List<DiscoveryNode> nodes = client.connectedNodes();
if (nodes.isEmpty()) {
LogKit.info("No NODES Connected");
}else {
for (DiscoveryNode node : nodes){
LogKit.info("节点信息:"+node.getHostName()+node.getName()+node.getHostAddress());
}
}
LogKit.info("ElasticsearchClient 连接成功,节点包括:"+ JSON.toJSON(client.listedNodes()));
} catch (UnknownHostException e) {
LogKit.info(e.getMessage());
}
return true;
}
@Override
public boolean stop() {
if (client != null){
client.close();
}
return true;
}
}三、启动插件
配置信息
elasticsearch_ip=127.0.0.1
elasticsearch_port=9300
cluster_name=elasticsearch
@Override
public void configPlugin(Plugins plugins) {
String ip = PropKit.get("elasticsearch_ip");
int port = PropKit.getInt("elasticsearch_port");
String cluster_name = PropKit.get("cluster_name");
plugins.add(new ElasticSearchPlugin(ip,port,cluster_name));
}四、搜索接口服务
import com.alibaba.fastjson.JSON;
import com.jfinal.ext.kit.DateKit;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Page;
import com.link.search.model.Article;
import com.link.search.model.SCPage;
import com.link.search.plugin.elasticsearch.ElasticSearchPlugin;
import com.link.search.service.SearchServiceI;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import java.util.*;
/**
* 搜索接口服务
* @author linkzz
* @create 2018-01-04 17:56
*/
public class SearchServiceImpl implements SearchServiceI {
/**
* 搜索
* @author linkzz
* @create 2018-01-10 10:11
*/
@Override
public SCPage<Article> searche(String keyword, Integer pageSize, Integer pageNo, String index, String type, String field) {
long start = System.currentTimeMillis();
LogKit.info("client信息:"+ JSON.toJSON(ElasticSearchPlugin.getClient().listedNodes()).toString());
QueryBuilder queryBuilders=null;
keyword = null == keyword ? "" : keyword;
pageSize = null == pageSize ? 10 : pageSize;
pageNo = null == pageNo ? 1 : pageNo;
HighlightBuilder hiBuilder = this.hiBuilder();
if ("All".equals(type)){
if (StrKit.notBlank(keyword)){
queryBuilders = QueryBuilders.queryStringQuery(keyword);
hiBuilder.field(field);
}else {
queryBuilders = QueryBuilders.matchAllQuery();
}
}
SearchResponse response = ElasticSearchPlugin.getClient().prepareSearch(index)
.setQuery(queryBuilders)
.setFrom((pageNo - 1) * pageSize)
.setSize(pageSize)
.highlighter(hiBuilder)
// 设置是否按查询匹配度排序
.setExplain(true)
.execute().actionGet();
SearchHits hits = response.getHits();
int total = (int) hits.getTotalHits();
int totalPage = total / pageSize;
if (total % pageSize == 0){
totalPage += 1;
}
List<Article> articles = new ArrayList<>();
for (SearchHit searchHit : hits){
Map source = searchHit.getSource();
Article article = JSON.parseObject(JSON.toJSONString(source),Article.class);
//获取高亮域
Map<String,HighlightField> result=searchHit.getHighlightFields();
//查询所有
if("All".equals(type)){
//从高亮域中取得指定域
HighlightField titlesField=result.get(field);
if(titlesField!=null){
//取得定于的高亮标签
Text[] nameTexts=titlesField.getFragments();
//为name串值增加自定义的高亮标签
String titles = "";
for(Text text:nameTexts){
titles += text;
}
LogKit.info("标题名称:"+titles.toString());
article.setTitle(titles.toString());
}
}
articles.add(article);
}
long end = System.currentTimeMillis();
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
SearchResponse searchResponse = ElasticSearchPlugin.getClient().prepareSearch(index).setQuery(queryBuilder).execute().actionGet();
SearchHits hi = searchResponse.getHits();
int totals=(int) hi.getTotalHits();
LogKit.info("在" + totals + "条记录中,搜索"+keyword+",共用时间 -->> " + (end - start) + " 毫秒");
SCPage<Article> page = new SCPage<>(articles,pageNo,pageSize,totalPage,total,totals,end - start);
return page;
}
/**
* 高亮处理
* @author linkzz
* @create 2018-01-10 10:10
*/
private HighlightBuilder hiBuilder(){
HighlightBuilder hiBuilder=new HighlightBuilder().field("*").requireFieldMatch(false);
hiBuilder.preTags("<span style=\"color:red\">");
hiBuilder.postTags("</span>");
//高亮内容长度
hiBuilder.fragmentSize(10000);
hiBuilder.requireFieldMatch(false);
return hiBuilder;
}
/**
* 测试索引
* @author linkzz
* @create 2018-01-10 10:11
*/
@Override
public boolean index() {
Map<String, Object> json = new HashMap<>();
json.put("title","测试index");
json.put("source","手动创建");
json.put("time", DateKit.toStr(new Date(),DateKit.timeStampPattern));
json.put("url","http://localhost:80");
LogKit.info("client信息:"+ JSON.toJSON(ElasticSearchPlugin.getClient().listedNodes()).toString());
IndexResponse response = ElasticSearchPlugin.getClient().prepareIndex("articl","content",String.valueOf(1))
.setSource(json)
.get();
LogKit.info("版本号:"+response.getVersion());
return false;
}
}五、调用服务
import com.jfinal.core.Controller;
import com.jfinal.kit.LogKit;
import com.link.search.model.Article;
import com.link.search.model.SCPage;
import com.link.search.service.SearchServiceI;
import com.link.search.service.impl.SearchServiceImpl;
/**
* 搜索管理
* @author linkzz
* @create 2018-01-04 9:13
*/
public class SearchController extends Controller {
SearchServiceI searchService = enhance(SearchServiceImpl.class);
public void index(){
String keyboard = getPara("keyboard");
int pageNo = getParaToInt("pageNo") == null ? 1 : getParaToInt("pageNo");
try {
SCPage<Article> page = searchService.searche(keyboard,10,pageNo,"articl","All","title");
setAttr("page",page);
setAttr("keyboard",keyboard);
} catch (Exception e) {
e.printStackTrace();
}
LogKit.info("调用搜索控制器,关键字参数为:"+keyboard);
render("result.html");
}
}六、效果
