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

Posted 程序员欣宸

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java与es8实战之四:SpringBoot应用中操作es8(无安全检查)相关的知识,希望对你有一定的参考价值。

欢迎访问我的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集群(无安全检查)

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 

    @Setter
    private 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;
    

    @Bean
    public ElasticsearchClient elasticsearchClient() 
        HttpHost[] httpHosts = toHttpHost();
        RestClient restClient = RestClient.builder(httpHosts).build();
        RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        return new ElasticsearchClient(transport);
    

    @Bean
    public 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 

    @Autowired
    private ElasticsearchClient elasticsearchClient;

    @Override
    public void addIndex(String name) throws IOException 
        ApplicationContext applicationContext;
        elasticsearchClient.indices().create(c -> c.index(name));
    

    @Override
    public boolean indexExists(String name) throws IOException 
        ApplicationContext a;
        return elasticsearchClient.indices().exists(b -> b.index(name)).value();
    

    @Override
    public void delIndex(String name) throws IOException 
        elasticsearchClient.indices().delete(c -> c.index(name));
    

    @Override
    public void create(String name,
                       Function<IndexSettings.Builder, ObjectBuilder<IndexSettings>> settingFn,
                       Function<TypeMapping.Builder, ObjectBuilder<TypeMapping>> mappingFn) throws IOException 
       elasticsearchClient
               .java与es8实战之五:SpringBoot应用中操作es8(带安全检查:https账号密码API Key)

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

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

java与es8实战之二:实战前的准备工作

java与es8实战之二:实战前的准备工作

java与es8实战之三:Java API Client有关的知识点串讲