第05课:整合常用技术框架之

第05课:整合常用技术框架之 Elasticsearch

前面为各位读者介绍了利用 Spring Boot 整合常用技术框架,如 JPA、Redis、MongoDB 以及 RabbitMQ,本文将重点讲解 Elasticsearch(简称 ES)在实际工作中如何使用。

利用 Spring Boot 整合 ES

Elasticsearch(简称 ES),是一个全文搜索引擎,同时可以作为 NoSQL 数据库,存储任意格式的文档和数据,也可以用于大数据的分析与统计。

ES是 Apache 开源的产品,其主要具有以下特点:

  1. 以 Lucene 为底层进行封装,为用户提供了一套简单、易用、风格一致的 RESTful 风格的 API 接口;
  2. 它以一种分布式的搜索引擎架构为用户提供服务,可以很容易的扩展到上百个节点,甚至更多,使系统具备高可用、高并发等特性;
  3. 支持 PB 级别数据查询,其主要用于大数据的查询、搜索、统计分析等。

通常用来操作 ES 的客户端有如下几种:

  1. TransportClient
  2. JestClient
  3. Spring Data Elasticsearch
  4. HttpClient

其中 HttpClient 主要是利用 ES 的原生 API 对其进行操作,在开发中不是太灵活,因此通常情况下不会选择其对 ES 进行操作。

利用 TransportClient、Spring Data Elasticsearch 对 ES 操作很方便。但随着 ES 版本的变更,相关的 API 也在不断的调整,因此有 ES 服务端版本变更之后,客户端的代码也要随之进行重新编写。

JestClient 对 ES 进行了封装,填补了 ES 在 HTTP Rest 接口客户端上的空白,它适用于 ES 2.0 以上的版本,无需因为 ES 服务端版本更改而对代码进行修改。本文我们将重要讲解 JestClient 客户端对 ES 的操作。

利用 JestClient 作为客户端对 ES 进行操作

该操作过程主要包括9步,接下来我们一一做下讲解。

1. 在 pom 文件中添加依赖,代码如下:

 <dependency>
    <groupId>io.searchbox</groupId>
    <artifactId>jest</artifactId>
    <version>5.3.3</version>
</dependency>

<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>6.3.0</version>
</dependency>

2. 在 application.yml 配置文件中添加 ES 连接配置信息,代码如下:

spring:
  elasticsearch:
    jest:
      url: http://192.168.1.120:9200
      username: hcb
      password: hcb13579
      readTimeout: 20000
      connectionTimeout: 20000

3. 读取配置信息:

@Configuration
@ConfigurationProperties(prefix = "spring.elasticsearch.jest")
public class EsClientConfiguration {
    /**
     * ES连接url
     */
    private String url;

    /**
     * ES连接用户名
     */
    private String username;

    /**
     * ES连接用密码
     */
    private String password;

    /**
     * ES 读取超时时间
     */
    private Integer readTimeout;

    /**
     * ES连接超时时间
     */
    private Integer connectionTimeout;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getReadTimeout() {
        return readTimeout;
    }

    public void setReadTimeout(Integer readTimeout) {
        this.readTimeout = readTimeout;
    }

    public Integer getConnectionTimeout() {
        return connectionTimeout;
    }

    public void setConnectionTimeout(Integer connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }
}

4. 添加获取 JestClient 实例工具类:

@Component
public class JestClientUtil {
    @Autowired
    private EsClientConfiguration esClientConfig;

    private JestClient jestClient = null;

    public JestClient createJestClient() {
        if (jestClient == null) {
            synchronized (this) {
                if (jestClient == null) {
                    JestClientFactory factory = new JestClientFactory();
                    factory.setHttpClientConfig(new HttpClientConfig

//设置连接es server url地址
.Builder(esClientConfig.getUrl())

//设置连接es用户名
.defaultCredentials(esClientConfig.getUsername()

//设置连接es密码
esClientConfig.getPassword())

//开启多线程模式
.multiThreaded(true)

//设置连接es最大超时时间
.connTimeout(esClientConfig.getConnectionTimeout())

//设置从es读取数据最大时间
.readTimeout(esClientConfig.getReadTimeout())

.build());

                    jestClient = factory.getObject();
                }
            }
        }

        return jestClient;
    }
}

5. 新建持久层 StudentRepository 接口:

public interface StudentRepository {
    /**
     * 添加学生
     *
     * @param student
     */
    void addStudent(Student student);

    /**
     * 批量添加学生
     *
     * @param students
     */
    void batchAddStudent(List<Student> students);

    /**
     * 根据学生信息查询学生信息
     *
     * @param studentName
     */
    List<Student> queryStudentByName(String studentName);

    /**
     * 创建索引
     */
    public void createIndex();
}

6. 新建持久层实现类 StudentRepositoryImpl:

@Repository("studentDao")
public class StudentRepositoryImpl implements StudentRepository {
    //es 索引名称
    private static final String ES_INDEX_NAME = "student_index";
    //es type名称
    private static final String ES_TYPE_NAME = "student_type";

    @Autowired
    private JestClientUtil jestClientUtil;

    //向索引中添加学生信息
    @Override
    public void addStudent(Student student) {
        Index index = new Index.Builder(student).index(this.ES_INDEX_NAME).
                type(this.ES_TYPE_NAME).build();
        try {
            //获取jestClient实例并向索引插入学生信息
            JestResult jestResult = jestClientUtil.createJestClient().execute(index);

            System.out.println(jestResult.isSucceeded());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //批量添加学生信息
    @Override
    public void batchAddStudent(List<Student> students) {
        if (!CollectionUtils.isEmpty(students)) {
            try {
                Bulk.Builder bulk = new Bulk.Builder().defaultIndex(this.ES_INDEX_NAME).
                        defaultType(this.ES_TYPE_NAME);
                //将学生列表信息循环假如bulk桶中
                for (Student student : students) {
                    Index index = new Index.Builder(student).build();
                    bulk.addAction(index);
                }

//获取jestClient实例并向index中插入学生信息
jestClientUtil.createJestClient().execute(bulk.build());
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }
    }

    //根据学生姓名查询学生信息
    @Override
    public List<Student> queryStudentByName(String studentName) {
        //实例化SearchSourceBuilder对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

//组装index 查询条件
searchSourceBuilder.query(QueryBuilders.matchQuery("name", studentName));

        //利用SearchSourceBuilder对象构建index查询对象
        Search search = new Search.Builder(searchSourceBuilder.toString())
                .addIndex(this.ES_INDEX_NAME).addType(this.ES_TYPE_NAME).build();
        try {
            //获取jestClient实例并向对index执行查询语句 
            JestResult result = jestClientUtil.createJestClient().execute(search);
            //获取查询结果
            return result.getSourceAsObjectList(Student.class);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    //创建es索引
    @Override
    public void createIndex() {
        try {
            jestClientUtil.createJestClient().execute(new CreateIndex.
                    Builder(this.ES_INDEX_NAME).build());
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
}

7. 新建服务层接口 StudentService 及其实现类 StudentServiceImpl:

public interface StudentService {
    /**
     * 添加学生信息
     * @param student
     * @return
     */
    void addStudent(Student student);

    /**
     * 批量添加学生信息
     * @param students
     * @return
     */
    void batchAddStudent(List<Student> students);


    /**
     * 根据学生姓名查询学生列表信息
     * @param studentName
     * @return
     */
    List<Student> queryStudentsByName(String studentName);

    /**
     * 创建索引
     */
    public void createIndex();
}

//定义学生信息服务接口实现类
@Service("studentService")
public class StudentServiceImpl implements StudentService {

    @Resource(name = "studentDao")
    private StudentRepository studentDao;

    //添加学生信息
    @Override
    public void addStudent(Student student) {
        studentDao.addStudent(student);
    }

    //批量添加学生信息
    @Override
    public void batchAddStudent(List<Student> students) {
    studentDao.batchAddStudent(students);
    }

    //根据学生姓名查询学生信息
    @Override
    public List<Student> queryStudentsByName(String studentName) {
        return studentDao.queryStudentByName(studentName);
    }

    //创建es索引
    @Override
    public void createIndex() {
        studentDao.createIndex();
    }
}

8. 新建控制层 EsClientController:

//控制器定义
@RequestMapping("/esClient")
@RestController
public class EsClientController {
    @Autowired
    private StudentService studentService;

    //添加学生信息
    @RequestMapping("/addStudent")
    public String addStudent(String studentName, Integer age) {
        Student student = new Student(UUID.randomUUID().toString(),
                studentName, age, new Date());

        studentService.addStudent(student);

        return "success";
    }

    //批量添加学生信息
    @RequestMapping("/batchAddStudent")
    public String batchAddStudent() {
        for (int i = 0; i < 100; i++) {
            Student student = new Student(UUID.randomUUID().toString(),
                    "黄家驹" + i, i + 1, new Date());
            studentService.addStudent(student);
        }

        return "success";
    }

    //根据学生姓名查询学生信息
    @RequestMapping("/queryStudentsWithName")
    public List<Student> queryStudentsByName(String studentName) {
        return studentService.queryStudentsByName(studentName);
    }

    //创建es索引
    @RequestMapping("/createIndex")
    public String queryStudentsByName() {
        studentService.createIndex();
        return "Success";
    }
}

9. 启动程序,利用 Postman 对新建索引,新增学生信息,查询学生信息接口分别进行测试。

(1)创建索引。

enter image description here

(2)新增学生信息。

enter image description here

(3)根据姓名查询学生信息。

enter image description here

由于篇幅问题,利用 JestClient 操作 ES 就为各位介绍到这里了,如果各位在工作中有任何问题,可以和我一起交流。

上一篇
下一篇
目录