0.引言
我们之间讲解了springboot整合spring data elasticsearch3.x。但elasticsearch的更新十分活跃,截止目前已经到了8.x版本。而spring data elasticsearch3.x所对应的es版本还是6.8.x
所以今天我们来讲解与spring-data-elasticsearch3.x有较大变化的spring data elasticsearch4.2.x版本如何整合到springboot
1. 版本差异
一些基础的概念性内容本文就不再重复讲解,不了解的可以查看之前的文章
spring data elasticsearch4.2.x与spring data elasticsearch3.x存在不少差异,这里仅列举我们搭建环境所涉及到的
日期类型格式声明
spring-data官方文档中可以看到申明日期类型的格式,DateFormat.none
和DateFormat.custom
已经被弃用
分片数声明
分片数、刷新时间等参数不再在@Docement
中声明,显示已经被弃用
取而代之,在@Setting
中声明
Repository声明
ElasticsearchCrudRepository
被取消,可以使用ElasticsearchRepository
替代,当然在3.x版本中也可以直接使用ElasticsearchRepository
2. 环境搭建
1、创建springboot项目,并引入spring web
、lombok
、spring-data-elasticsearch
依赖
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>4.2.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.11</version>
</dependency>
2、修改配置文件
spring:
application:
name: es-test4
elasticsearch:
rest:
uris: http://192.168.244.11:9200 # 多个地址用逗号隔开
username: elastic # es开启了security的需要添加用户名和账户
password: elastic # es开启了security的需要添加用户名和账户
jackson:
date-format: yyyy-MM-dd HH:mm:ss
3、创建实体类
/**
* @author whx
* @date 2022/7/2
*/
@Data
@Document(indexName = "user")
@Setting(replicas = 0,shards = 1)
public class User implements Serializable {
@Id
private String id;
@Field(type = FieldType.Text, name = "name",analyzer = "standard")
private String name;
@Field(type = FieldType.Keyword, name = "password")
private String password;
@Field(type = FieldType.Integer, name = "sex")
private Integer sex;
@Field(type = FieldType.Text, name = "address", analyzer = "ik_smart")
private String address;
@Field(type = FieldType.Date, name = "create_date", pattern="yyyy-MM-dd HH:mm:ss||strict_date_optional_time||epoch_millis")
private Date createDate;
@Field(type = FieldType.Long, name = "role_ids")
private List<Long> roleIds;
@Field(type = FieldType.Nested, name = "department_list")
private List<Department> departmentList;
}
@Data
public class Department implements Serializable {
@Field(type = FieldType.Long, name = "id")
private Long id;
@Field(type = FieldType.Keyword, name = "name")
private String name;
}
4、创建Repository
类,用于实现简单的CRUD,其中的自定义方法可以参考上篇3.x版本的文章介绍
import com.example.estest.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
/**
* @author whx
* @date 2022/7/2
*/
public interface UserRepository extends ElasticsearchRepository<User,String> {
User findByName(String name);
List<User> findAllByName(String name);
Page<User> findAllByName(String name, Pageable pageable);
@Query("{\"term\": {\"name\": {\"value\": \"?0\"}}}")
User queryByName(String name);
}
5、实现Controller
import com.example.estest.entity.User;
import com.example.estest.repository.UserRepository;
import lombok.AllArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author whx
* @date 2022/7/2
*/
@RestController
@RequestMapping("user")
@AllArgsConstructor
public class UserController {
private final UserRepository userRepository;
@GetMapping("getByName")
public User getByName(String name){
return userRepository.findByName(name);
}
@GetMapping("getAllByName")
public List<User> getAllByName(String name){
return userRepository.findAllByName(name);
}
@GetMapping("pageAllByName")
public Page<User> pageAllByName(String name,int page,int size){
return userRepository.findAllByName(name,PageRequest.of(page,size));
}
@GetMapping("queryByName")
public User queryByName(String name){
return userRepository.queryByName(name);
}
@PostMapping("save")
public String add(@RequestBody User user){
try{
userRepository.save(user);
return "保存成功";
}catch (Exception e){
e.printStackTrace();
return "保存失败";
}
}
}
6、创建ElasticRestClientConfig
配置类,声明RestHighLevelClient
和ElasticsearchRestTemplate
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
import java.time.Duration;
/**
* @author whx
* @date 2022/7/2
*/
@Configuration
@EnableElasticsearchRepositories(basePackages = "com.example.estest")
public class ElasticRestClientConfig extends AbstractElasticsearchConfiguration {
@Value("${spring.elasticsearch.rest.uris}")
private String url;
@Value("${spring.elasticsearch.rest.username}")
private String username;
@Value("${spring.elasticsearch.rest.password}")
private String password;
@Override
@Bean
public RestHighLevelClient elasticsearchClient() {
url = url.replace("http://","");
String[] urlArr = url.split(",");
HttpHost[] httpPostArr = new HttpHost[urlArr.length];
for (int i = 0; i < urlArr.length; i++) {
HttpHost httpHost = new HttpHost(urlArr[i].split(":")[0].trim(),
Integer.parseInt(urlArr[i].split(":")[1].trim()), "http");
httpPostArr[i] = httpHost;
}
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(username,password));
RestClientBuilder builder = RestClient.builder(httpPostArr)
// 异步httpclient配置
.setHttpClientConfigCallback(httpClientBuilder -> {
// 账号密码登录
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
// httpclient连接数配置
httpClientBuilder.setMaxConnTotal(30);
httpClientBuilder.setMaxConnPerRoute(10);
// httpclient保活策略
httpClientBuilder.setKeepAliveStrategy(((response, context) -> Duration.ofMinutes(5).toMillis()));
return httpClientBuilder;
});
return new RestHighLevelClient(builder);
}
@Bean
public ElasticsearchRestTemplate elasticsearchRestTemplate(RestHighLevelClient elasticsearchClient,ElasticsearchConverter elasticsearchConverter){
return new ElasticsearchRestTemplate(elasticsearchClient,elasticsearchConverter);
}
}
7、如果需要启动项目时自动创建索引,还可以添加索引创建类
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import java.util.Set;
/**
* @author whx
* @date 2022/7/2
*/
@Configuration
@Slf4j
@AllArgsConstructor
public class ElasticCreateIndexStartUp implements ApplicationListener<ContextRefreshedEvent> {
private final ElasticsearchRestTemplate restTemplate;
@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent){
log.info("[elastic]索引初始化...");
Reflections f = new Reflections("com.example.estest.entity");
Set<Class<?>> classSet = f.getTypesAnnotatedWith(Document.class);
for (Class<?> clazz : classSet) {
IndexOperations indexOperations = restTemplate.indexOps(clazz);
if(!indexOperations.exists()){
indexOperations.create();
indexOperations.putMapping();
log.info(String.format("[elastic]索引%s数据结构创建成功",clazz.getSimpleName()));
}
}
log.info("[elastic]索引初始化完毕");
}
}
8、启动项目
9、调用保存接口
10、调用查询接口
项目接口正常,环境搭建成功!