欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本篇是《java与es8实战》系列的第四篇,系列文章写到现在,连个HelloWorld都没运行起来,实在说不过去了…
  • 因此,本篇总体目标明确:实战在SpringBoot应用中操作elasticsearch8
  • 为了降低难度,本篇部署的elasticsearch8未设置安全检查,无需证书、账号、密码,只要连接到es的IP和端口就能执行操作
  • 总体目标可以拆解为两个子任务
  1. 在SpringBoot中连接elasticsearch8
  2. 在SpringBoot中使用elasticsearch8官方的Java API Client
  • 接下来直接开始

部署elasticsearch集群(无安全检查)

  • 关于快速部署elasticsearch集群(无安全检查),可以参考《docker-compose快速部署elasticsearch-8.x集群+kibana》

Java应用连接elasticsearch的核心套路

  • 不论是直连,还是带安全检查的连接,亦或是与SpringBoot的集成使之更方便易用,都紧紧围绕着一个不变的核心套路,该套路由两部分组成,掌握了它们就能在各种条件下成功连接es
  1. 首先,是builder pattern,连接es有关的代码,各种对象都是其builder对象的build方法创建的,建议您提前阅读《java与es8实战之一》一文,看完后,满屏的builder代码可以从丑变成美…
  2. 其次,就是java应用能向es发请求的关键:ElasticsearchClient对象,该对象的创建是有套路的,如下图,先创建RestClient,再基于RestClient创建ElasticsearchTransport,最后基于ElasticsearchTransport创建ElasticsearchClient,这是个固定的套路,咱们后面的操作都是基于此的,可能会加一点东西,但不会改变流程和图中的对象
  • 准备完毕,开始写代码

新建子工程

  • 为了便于管理依赖库版本和源码,《java与es8实战》系列的所有代码都以子工程的形式存放在父工程elasticsearch-tutorials中

  • 《java与es8实战之二:实战前的准备工作》一文说明了创建父工程的详细过程

  • 在父工程elasticsearch-tutorials中新建名为basic-crud的子工程,其pom.xml内容如下

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><!-- 请改为自己项目的parent坐标 --><parent><artifactId>elasticsearch-tutorials</artifactId><groupId>com.bolingcavalry</groupId><version>1.0-SNAPSHOT</version><relativePath>../pom.xml</relativePath></parent><modelVersion>4.0.0</modelVersion><!-- 请改为自己项目的artifactId --><artifactId>basic-crud</artifactId><packaging>jar</packaging><!-- 请改为自己项目的name --><name>basic-crud</name><url>https://github.com/zq2599</url><!--不用spring-boot-starter-parent作为parent时的配置--><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${springboot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!-- 不加这个,configuration类中,IDEA总会添加一些提示 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><optional>true</optional></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><!-- exclude junit 4 --><exclusions><exclusion><groupId>junit</groupId><artifactId>junit</artifactId></exclusion></exclusions></dependency><!-- junit 5 --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><scope>test</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><scope>test</scope></dependency><!-- elasticsearch引入依赖  start --><dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId></dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></dependency><!-- 使用spring boot Maven插件时需要添加该依赖 --><dependency><groupId>jakarta.json</groupId><artifactId>jakarta.json-api</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies><build><plugins><!-- 需要此插件,在执行mvn test命令时才会执行单元测试 --><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-surefire-plugin</artifactId><version>3.0.0-M4</version><configuration><skipTests>false</skipTests></configuration></plugin><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins><resources><resource><directory>src/main/resources</directory><includes><include>**/*.*</include></includes></resource></resources></build>
</project>

编码:配置文件

  • 先准备好配置文件application.yml,内容如下,很简单,只有es的地址信息
elasticsearch:# 多个IP逗号隔开hosts: 127.0.0.1:9200

编码:配置类

  • 首先把启动类写好,平平无奇的启动类BasicCrudApplication.java
@SpringBootApplication
public class BasicCrudApplication {public static void main(String[] args) {SpringApplication.run(BasicCrudApplication.class, args);}
}
  • 然后是配置类ClientConfig.java,这是本篇的关键,操作ES所需的ElasticsearchClient实例如何创建,ES的IP地址如何传入,全部写在这里了
package com.bolingcavalry.basic.config;import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import lombok.Setter;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;@ConfigurationProperties(prefix = "elasticsearch") //配置的前缀
@Configuration
public class ClientConfig {@Setterprivate String hosts;/*** 解析配置的字符串,转为HttpHost对象数组* @return*/private HttpHost[] toHttpHost() {if (!StringUtils.hasLength(hosts)) {throw new RuntimeException("invalid elasticsearch configuration");}String[] hostArray = hosts.split(",");HttpHost[] httpHosts = new HttpHost[hostArray.length];HttpHost httpHost;for (int i = 0; i < hostArray.length; i++) {String[] strings = hostArray[i].split(":");httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]), "http");httpHosts[i] = httpHost;}return httpHosts;}@Beanpublic ElasticsearchClient elasticsearchClient() {HttpHost[] httpHosts = toHttpHost();RestClient restClient = RestClient.builder(httpHosts).build();RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());return new ElasticsearchClient(transport);}@Beanpublic ElasticsearchAsyncClient elasticsearchAsyncClient() {HttpHost[] httpHosts = toHttpHost();RestClient restClient = RestClient.builder(httpHosts).build();RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());return new ElasticsearchAsyncClient(transport);}
}
  • 从上面的代码可以看出,配置类已经向Spring容器注册了ElasticsearchClient实例,后面的业务都可以使用此实例来操作ES

编码:服务类

  • 本篇只是为了演示SpringBoot应用如何连接和操作ES,还不会深入ES操作的细节,因此只对索引做一些基本操作即可

  • 先写一个接口IndexService.java,里面定义了多个索引操作的方法

package com.bolingcavalry.basic.service;import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import co.elastic.clients.util.ObjectBuilder;import java.io.IOException;
import java.util.function.Function;public interface IndexService {/*** 新建指定名称的索引* @param name* @throws IOException*/void addIndex(String name) throws IOException;/*** 检查指定名称的索引是否存在* @param name* @return* @throws IOException*/boolean indexExists(String name) throws IOException;/*** 删除指定索引* @param name* @throws IOException*/void delIndex(String name) throws IOException;/*** 创建索引,指定setting和mapping* @param name 索引名称* @param settingFn 索引参数* @param mappingFn 索引结构* @throws IOException*/void create(String name,Function<IndexSettings.Builder, ObjectBuilder<IndexSettings>> settingFn,Function<TypeMapping.Builder, ObjectBuilder<TypeMapping>> mappingFn) throws IOException;
}
  • 然后接口的实现,可见所有操作都是在调用ElasticsearchClient实例的API
package com.bolingcavalry.basic.service.impl;import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import co.elastic.clients.util.ObjectBuilder;
import com.bolingcavalry.basic.service.IndexService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;import java.io.IOException;
import java.util.function.Function;@Service
public class IndexServiceImpl implements IndexService {@Autowiredprivate ElasticsearchClient elasticsearchClient;@Overridepublic void addIndex(String name) throws IOException {ApplicationContext applicationContext;elasticsearchClient.indices().create(c -> c.index(name));}@Overridepublic boolean indexExists(String name) throws IOException {ApplicationContext a;return elasticsearchClient.indices().exists(b -> b.index(name)).value();}@Overridepublic void delIndex(String name) throws IOException {elasticsearchClient.indices().delete(c -> c.index(name));}@Overridepublic void create(String name,Function<IndexSettings.Builder, ObjectBuilder<IndexSettings>> settingFn,Function<TypeMapping.Builder, ObjectBuilder<TypeMapping>> mappingFn) throws IOException {elasticsearchClient.indices().create(c -> c.index(name).settings(settingFn).mappings(mappingFn));}
}
  • 以上就是本篇的功能代码了,连接ES在其上进行索引相关操作

编码:单元测试

  • 为了验证上述代码是否生效,接下来写一个单元测试类IndexServiceTest.java,可以重点关注createIndex方法,里面演示了Builder pattern构建参数的详细步骤
package com.bolingcavalry.basic.service;import co.elastic.clients.elasticsearch._types.mapping.Property;
import co.elastic.clients.elasticsearch._types.mapping.TypeMapping;
import co.elastic.clients.elasticsearch.indices.IndexSettings;
import co.elastic.clients.util.ObjectBuilder;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.function.Function;@SpringBootTest
class IndexServiceTest {@AutowiredIndexService indexService;@Testvoid addIndex() throws Exception {String indexName = "test_index";Assertions.assertFalse(indexService.indexExists(indexName));indexService.addIndex(indexName);Assertions.assertTrue(indexService.indexExists(indexName));indexService.delIndex(indexName);Assertions.assertFalse(indexService.indexExists(indexName));}@Testvoid indexExists() throws Exception {indexService.indexExists("a");}@Testvoid createIndex() throws Exception {// 索引名String indexName = "product002";// 构建setting时,builder用到的lambdaFunction<IndexSettings.Builder, ObjectBuilder<IndexSettings>> settingFn = sBuilder -> sBuilder.index(iBuilder -> iBuilder// 三个分片.numberOfShards("3")// 一个副本.numberOfReplicas("1"));// 新的索引有三个字段,每个字段都有自己的property,这里依次创建Property keywordProperty = Property.of(pBuilder -> pBuilder.keyword(kBuilder -> kBuilder.ignoreAbove(256)));Property textProperty = Property.of(pBuilder -> pBuilder.text(tBuilder -> tBuilder));Property integerProperty = Property.of(pBuilder -> pBuilder.integer(iBuilder -> iBuilder));// // 构建mapping时,builder用到的lambdaFunction<TypeMapping.Builder, ObjectBuilder<TypeMapping>> mappingFn = mBuilder -> mBuilder.properties("name", keywordProperty).properties("description", textProperty).properties("price", integerProperty);// 创建索引,并且指定了setting和mappingindexService.create(indexName, settingFn, mappingFn);}
}
  • 确保不做安全检查的ES集群运行正常,再执行单元测试,如下图,顺利通过,证明所有对ES的操作都符合预期
  • 再用eshead观察product002索引的情况,如下图,三个分片,一个副本,与代码中设置的一致
  • 至此最简单的连接和操作ES实战已经完成,希望本篇能给您一些参考,助您顺利完成基本操作

是不是线程安全的

  • 官方回应:https://discuss.elastic.co/t/is-elasticsearch-client-is-thread-safe/151745
  • 有人在问这个问题,es团队的成员Simon Willnauer的回答是:java的client肯定是线程安全的,golang的不清楚
  • 对我来说,有他这话就够了,至于golang的嘛,在本文就不讨论了

源码下载

  • 本篇实战的完整源码可在GitHub下载到,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos)
名称 链接 备注
项目主页 https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
git仓库地址(https) https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
git仓库地址(ssh) git@github.com:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议
  • 这个git项目中有多个文件夹,本次实战的源码在elasticsearch-tutorials文件夹下,如下图红框
  • elasticsearch-tutorials是个父工程,里面有多个module,本篇实战的module是basic-crud,如下图红框

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

java与es8实战之四:SpringBoot应用中操作es8(无安全检查)相关推荐

  1. java与es8实战之五:SpringBoot应用中操作es8(带安全检查:https、账号密码、API Key)

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本篇是<java与es8实战>系 ...

  2. java版gRPC实战之四:客户端流

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos <java版gRPC实战>全系列链接 用p ...

  3. 阿里技术专家加多:Java异步编程实战之基于JDK中的Future实现异步编程 | 文末赠书...

    正文共:14244 字 8 图 预计阅读时间: 36 分钟 本节内容摘自<Java异步编程实战>中的一小节. 一.前言 本节主要讲解如何使用JDK中的Future实现异步编程,这包含如何使 ...

  4. 阿里技术专家加多:Java异步编程实战之基于JDK中的Future实现异步编程

    正文共:14244 字 8 图 预计阅读时间: 36 分钟 本节内容摘自<Java异步编程实战>中的一小节. 一.前言 本节主要讲解如何使用JDK中的Future实现异步编程,这包含如何使 ...

  5. java并发编程实战程序5-19

    验证Java并发编程实战程序清单5-19中memorizer.compute对于相同参数的请求只有一个能进Map import org.junit.Test;import java.util.conc ...

  6. Java并发编程实战之互斥锁

    文章目录 Java并发编程实战之互斥锁 如何解决原子性问题? 锁模型 Java synchronized 关键字 Java synchronized 关键字 只能解决原子性问题? 如何正确使用Java ...

  7. Java秒杀系统实战系列~构建SpringBoot多模块项目

    摘要:本篇博文是"Java秒杀系统实战系列文章"的第二篇,主要分享介绍如何采用IDEA,基于SpringBoot+SpringMVC+Mybatis+分布式中间件构建一个多模块的项 ...

  8. java与es8实战之一:以builder pattern开篇

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 关于<java与es8实战>系列 < ...

  9. 亲测简单易懂可用:阿里云OSS入门实战2(集成到SpringBoot项目中存放用户头像)

    亲测简单易懂可用:阿里云OSS入门实战2(集成到SpringBoot项目中存放用户头像) 大噶好,我们继续延续上一章,学习如何使用OSS存放用户头像代码示例; 在application.propert ...

最新文章

  1. IOS 内存管理小结
  2. python中定义字符串_python中的字符串
  3. nmap扫描局域网存活主机_安全工程师都在用的网络扫描软件,巧用ARP协议发现主机。第二节...
  4. 如何高效备考信息系统项目管理师?
  5. 疫情反复,电赛会取消吗?
  6. OSG——- 对点选物体平移(鼠标点选物体、物体随鼠标移动、屏幕坐标转世界坐标)
  7. LU分解算法(串行、并行)
  8. Python基础教学3:变量名和赋值
  9. 前后端分离实现上传图片的功能
  10. 新王诞生!ACP世界大赛中国区总决赛超燃收官!
  11. html邢台模板,邢台水泥预制件定制
  12. SQL面试题整理_数据库知识点
  13. 明日之后营地14庄中式风房子上线,网友:都是氪金大佬
  14. lua生成指定大小的随机字符串
  15. matlab成功安装libsvm后,运行程序仍报错“svmtrain has been removed”解决方法记录
  16. linux命令 移动/复制文件/目录到指定目录下
  17. pytorch安装和tensorflow环境搭建和cuda加速和cudann安装教程记录日期2022.10.20日
  18. 支付宝小程序唤起签约并支付(周期扣款)
  19. 五大方面:机器学习如何在不久的将来改变教育
  20. HD声卡与AC97声卡设置方法及原理

热门文章

  1. 代码报错 Uncaught TypeError: Converting circular structure to JSON
  2. ES1J-ASEMI超快恢复二极管ES1J
  3. html 掉爱心特效,微信发什么会掉爱心特效(微信特效词语合集)
  4. 线代9讲_特征值与特征向量相似理论
  5. 令人匪夷所思的 Magic 之魔数,你真的不会
  6. Android开发:开源库集合
  7. Vue的video-player的视频无法加载出来,vue视频插件;显示叉号; The media could not be Loaded,
  8. php数组函数array flip,PHP array_flip() 函数
  9. 计算机10进制化2进制在线,二进制转十进制
  10. 搭建手机文件服务器,普通用户的低成本家庭文件服务器(伪NAS)的搭建(手机备份篇)...