龙空技术网

「Spring Boot 集成应用」ElasticSearch的集成配置使用

Mirson架构之道 882

前言:

此刻大家对“集成配置什么意思”都比较关怀,你们都需要分析一些“集成配置什么意思”的相关知识。那么小编在网上汇集了一些有关“集成配置什么意思””的相关内容,希望看官们能喜欢,同学们一起来了解一下吧!

1. Spring Boot 与ES集成简介

Spring-boot支持ElasticSearch的集成, 并提供了spring-boot-starter-data-elasticsearch自动化配置组件。 这里会介绍如何通过该组件, 集成至项目中使用, 并实现基本的增删改查功能,同时演示集成的一些高级用法, 比如流式查询、自定义查询和异步查询。

2. 工程创建

创建工程spring-boot-elasticsearch

启动类:

com.mirson.spring.boot.elastic.startup.ElasticSearchApplication

@SpringBootApplication@ComponentScan(basePackages = {"com.mirson"})@EnableElasticsearchRepositories(basePackages = {"com.mirson"})public class ElasticSearchApplication {    public static void main(String[] args) {        SpringApplication.run(ElasticSearchApplication.class, args);    }}

需要开启EnableElasticsearchRepositories注解, 扫描Repositories接口。

3. 集成配置POM依赖

<dependencies>      <!-- Spring Boot Web 依赖组件 -->      <dependency>          <groupId>org.springframework.boot</groupId>          <artifactId>spring-boot-starter-web</artifactId>      </dependency>      <!-- Spring Boot Data ElasticSearch 依赖组件 -->      <dependency>          <groupId>org.springframework.boot</groupId>          <artifactId>spring-boot-starter-data-elasticsearch</artifactId>      </dependency>  </dependencies>

采用spring-boot-starter-data-elasticsearch组件, Spring Boot 提供的elasticsearch自动化配置。

工程配置

application.yml

# 服务端口server:  port: 22716# 服务名称spring:  application:    name: boot-es  data:    elasticsearch:      # 集群名称      cluster-name: my-application      # 节点的地址, 注意采用的API端口, 非服务端口      cluster-nodes: 10.10.20.15:9300      # 是否开启本地存储      repositories:        enabled: true

注意, 这里采用的是ElasticSearch的API端口, 非服务端口。

4. 实现CURD功能实现4.1 创建实体

新建com.mirson.spring.boot.elastic.po.User

@Data@Document(indexName = "business",type = "user", shards = 1,replicas = 0, refreshInterval = "-1")public class User {    /**     * ID     */    @Id    private Integer id;    /**     * 用户名称     */    private String name;    /**     * 年龄     */    private String age;    /**     * 地址     */    private String address;    /**     * 创建时间     */    private Date createDate;}

加上Document注解, 指定index为business, type为user。

4.2 创建Repository资源接口

新建com.mirson.spring.boot.elastic.repository.UserRepository

@Repositorypublic interface UserRepository extends ElasticsearchRepository<User,Integer> {    /**     * 根据名称查找对象, 模糊匹配     * @param name     * @return     */    List<User> findByNameLike(String name);}

提供根据名称查找用户对象的接口, 支持模糊查询,Repository还提供更多用法, 详情参考以下表格:

关键词

示例

Elasticsearch查询字符串

And

findByNameAndPrice

{"bool" : {"must" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}

Or

findByNameOrPrice

{"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"price" : "?"}} ]}}

Is

findByName

{"bool" : {"must" : {"field" : {"name" : "?"}}}}

Not

findByNameNot

{"bool" : {"must_not" : {"field" : {"name" : "?"}}}}

Between

findByPriceBetween

{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}

LessThanEqual

findByPriceLessThan

{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}

GreaterThanEqual

findByPriceGreaterThan

{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}

Before

findByPriceBefore

{"bool" : {"must" : {"range" : {"price" : {"from" : null,"to" : ?,"include_lower" : true,"include_upper" : true}}}}}

After

findByPriceAfter

{"bool" : {"must" : {"range" : {"price" : {"from" : ?,"to" : null,"include_lower" : true,"include_upper" : true}}}}}

Like

findByNameLike

{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}

StartingWith

findByNameStartingWith

{"bool" : {"must" : {"field" : {"name" : {"query" : "?*","analyze_wildcard" : true}}}}}

EndingWith

findByNameEndingWith

{"bool" : {"must" : {"field" : {"name" : {"query" : "*?","analyze_wildcard" : true}}}}}

Contains/Containing

findByNameContaining

{"bool" : {"must" : {"field" : {"name" : {"query" : "**?**","analyze_wildcard" : true}}}}}

In

findByNameIn(Collection<String>names)

{"bool" : {"must" : {"bool" : {"should" : [ {"field" : {"name" : "?"}}, {"field" : {"name" : "?"}} ]}}}}

NotIn

findByNameNotIn(Collection<String>names)

{"bool" : {"must_not" : {"bool" : {"should" : {"field" : {"name" : "?"}}}}}}

Near

findByStoreNear

Not Supported Yet !

True

findByAvailableTrue

{"bool" : {"must" : {"field" : {"available" : true}}}}

False

findByAvailableFalse

{"bool" : {"must" : {"field" : {"available" : false}}}}

OrderBy

findByAvailableTrueOrderByNameDesc

{"sort" : [{ "name" : {"order" : "desc"} }],"bool" : {"must" : {"field" : {"available" : true}}}}

4.3 提供保存更新接口

新建com.mirson.spring.boot.elastic.controller.UserController

@RestController@Log4j2public class UserController {    @Autowired    private UserRepository userRepository;    /**     * 添加用户     * @param user     * @return     */    @RequestMapping("/add")    public String add(User user) {        log.info("Process in add method. user:  " + user);        User result = userRepository.save(user);        log.info(" add result : " + result);        return "add success.";    }    ...}

如果不指定ID, 则会新增数据; 指定ID参数, 将会进行更新操作。

4.4 提供查找接口

com.mirson.spring.boot.elastic.controller.UserController增加:

    /**     * 查找用户     * @param name     * @return     */    @RequestMapping("/find")    public List<User> find(String name) {        log.info("Process in find method. name:  " + name);        List<User> user = userRepository.findByNameLike(name);        return user;    }
4.5 提供删除接口

com.mirson.spring.boot.elastic.controller.UserController增加:

    /**     * 删除用户     * @return     */    @RequestMapping("/del")    public String del(Integer id) {        log.info("Process in del method. id:  " + id);        userRepository.deleteById(id);        return "delete success. ";    }
5. ES集成高级用法5.1 流式查询UserRepository

增加接口:

/** * 获取所有对象 * @param pageable * @return */Stream<User> streamAllByNameLike(String name);    

对于大数据量情况下, 可以采用Stream流式处理, 使用完必须要释放资源, 可以通过Java 7的 try-with-resources来自动处理。 不同流式用法参照:

@Query("select u from User u")Stream<User> findAllByCustomQueryAndStream();Stream<User> readAllByFirstnameNotNull();@Query("select u from User u")Stream<User> streamAllPaged(Pageable pageable);
Web接口

com.mirson.spring.boot.elastic.controller.UserController

    /**     * 流式查询     * @param name     * @return     */    @RequestMapping("/stream")    public String stream(String name) {        log.info("Process in stream method. name:  " + name);        StringBuffer sbf = new StringBuffer();        // try-with-resources 处理资源, 自动关闭stream流资源        try (Stream<User> stream = userRepository.streamAllByNameLike(name)) {            stream.forEach(user -> {                sbf.append("userName: ").append(user.getName()).append(",");            });        }        return sbf.toString().replaceAll(",$", "");    }

采用 try-with-resources方式, 自动释放流资源。

5.2 自定义查询UserRepository

增加接口:

/** * 自定义查询, 根据用户名称获取对象 * @param name * @return */@Query("{\"bool\" : {\"must\" : {\"match\" : {\"name\" : \"?0\"}}}}")List<User> customByName(String name);    

自定义根据名称查询, 完全匹配模式。

Web接口

com.mirson.spring.boot.elastic.controller.UserController增加:

/** * 自定义查询 * @param name * @return */@RequestMapping("/custom")public List<User> custom(String name) {    log.info("Process in custom method. name:  " + name);    List<User> user = userRepository.customByName(name);    return user;}

5.3 异步查询UserRepository

增加接口:

/** * 异步查询, 根据名称获取对象 * @param name * @return */@AsyncFuture<User> findOneByName(String name);

加上Async注解, 返回对象采用Futrue包装。

其他用法示例参照:

@AsyncFuture<User> findByFirstname(String firstname);               @AsyncCompletableFuture<User> findOneByFirstname(String firstname); @AsyncListenableFuture<User> findOneByLastname(String lastname);  

1)使用java.util.concurrent.Future作为返回类型。

2) 使用Java 8 java.util.concurrent.CompletableFuture作为返回类型。

3)使用a org.springframework.util.concurrent.ListenableFuture作为返回类型。

Web层接口

UserController增加:

/** * 异步查询 * @param name * @return */@RequestMapping("/async")public List<User> async(String name) throws Exception {    log.info("Process in async method. name:  " + name);    Future<User> userTask = userRepository.findOneByName(name);    User user = userTask.get();    return Arrays.asList(user);}
6. 功能测试6.1 CURD功能验证新增功能

创建ID为1, 名称为user1, 年龄为21, 地址为广东省深圳市宝安区1的数据

采用POST方式,创建成功。

更新功能

修改名称为user对象, 将年龄由21改为31, 注意ID必须指定正确。

返回成功。

查询功能

查询名称为user1的对象

成功返回数据, 年龄已修改为31。

删除功能

根据ID进行删除, 将ID为1的数据删除。

再次查询:

数据不存在。

6.2 高级功能验证

先创建三条数据。

流式查询

将三条数据成功输出。

自定义查询

成功找到user1对象。

异步查询

根据指定参数, 成功找到user2对象。

7. 总结

这里通过对spring-boot-starter-data-elasticsearch组件的使用, 掌握了Spring Boot与 ES的集成用法, 实现基本的CURD功能, 同时掌握一些高级特性, 比如流式查询和异步查询等。这些功能基本可以满足大多数项目中的使用, 更多高级特性可以再深入研究官方手册。

标签: #集成配置什么意思