一、版本依赖
<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"); } }
六、效果