SpringBoot整合ES(REST Client方式)并实现简单的增删改查

首先有三种方式可以实现在java代码里操作ES,分别是Java API(TransportClient客户端),REST Client以及Data-ES,对于第一种,ES官方表示将在ES 8.0版本弃用,所以不是我们学习的重点。至于Data-ES,虽然它和SpringBoot集成的很好,容易上手,而且提供了很方便的api,但是据说不支持ES的权限数据,如果只是很简单的获取普通数据,Data-ES将是很好的一个方式。但如果需要获取权限数据呢?

集成准备工作

首先pom依赖如下

    
        
        
            org.springframework.boot
            spring-boot-starter
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-configuration-processor
            true
        
        
        
            org.elasticsearch
            elasticsearch
            6.8.4
        
        
            org.elasticsearch.client
            elasticsearch-rest-client
            6.8.4
        
        
            org.elasticsearch.plugin
            reindex-client
            6.8.4
        
        
        
            com.alibaba
            fastjson
            1.2.54
        
        
            org.apache.commons
            commons-lang3
        
        
            org.projectlombok
            lombok
            true
        
        
        
            io.springfox
            springfox-swagger2
            2.7.0
        
        
            io.springfox
            springfox-swagger-ui
            2.7.0
        
        
            io.springfox
            springfox-staticdocs
            2.4.0
        
        
            io.github.robwin
            assertj-swagger
            0.2.0
            test
        

    

然后是yml文件

server:
  port: 8080

swagger:
  enable: true
  title: ElasticSearch-demo
  description:
  serviceUrl: http://localhost:8080/
  version: 1.0.0
  controllers: com.example.es.controller

elasticsearch:
  user:
  password:
  host: 192.168.145.128
  port: 9200

PS:swagger和lombok是好东西

代码实现

配置类:

@Configuration
@Slf4j
public class ESConfig {

    @Value("${elasticsearch.user}")
    private String userName;
    @Value("${elasticsearch.password}")
    private String password;
    @Value("${elasticsearch.host}")
    private String host;
    @Value("${elasticsearch.port}")
    private Integer port;

    @Bean(name = "myClient")
    public RestClient getRestClient() {
        //基本的连接
        RestClientBuilder clientBuilder = RestClient.builder(new HttpHost(host, port));
        //配置身份验证
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(userName, password));
        clientBuilder.setHttpClientConfigCallback(
                httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
        //设置连接超时和套接字超时
        clientBuilder.setRequestConfigCallback(builder -> builder.setConnectTimeout(10000).setSocketTimeout(60000));
        //设置节点选择器
        clientBuilder.setNodeSelector(NodeSelector.SKIP_DEDICATED_MASTERS);
        //配置HTTP异步请求ES的线程数
        clientBuilder.setHttpClientConfigCallback(
                httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultIOReactorConfig(
                        IOReactorConfig.custom().setIoThreadCount(1).build()));
        //设置监听器,每次节点失败都可以监听到,可以作额外处理
        clientBuilder.setFailureListener(new RestClient.FailureListener() {
            @Override
            public void onFailure(Node node) {
                super.onFailure(node);
                log.error(node.getHost() + "--->该节点失败了");
            }
        });

        return clientBuilder.build();
    }


}

这样的话,已经算是集成到springboot了,但是如何实现增删改查?

首先引入两个bean,后续的代码有用

Person类,这个是我们接下来要操作的实体类

@Data
public class Person {

    private String id;
    private String name;
    private String birthday;
    private String addr;

}

SearchParam类,用于拼接请求内容,包括index,type和id

@Data
public class SearchParam {

    @ApiModelProperty("索引")
    private String index;
    @ApiModelProperty("类型")
    private String type;
    @ApiModelProperty("id")
    private String id;

}

接下来是Controller层的代码

@RestController
@RequestMapping("/es")
public class MyController {

    @Autowired
    private MyService service;

    @PostMapping("/search")
    @ApiOperation("根据id查询ES对应的数据")
    public JSONObject getDataById(@RequestBody SearchParam param) {
        return service.getDataById(param);
    }

    @PostMapping("/add")
    @ApiOperation("往ES里插入数据")
    public ResponseEntity add(@RequestBody SearchParam param) {
        return service.add(param);
    }

    @PostMapping("/update")
    @ApiOperation("根据id更新文档内容")
    public ResponseEntity update(@RequestBody SearchParam param) {
        return service.update(param);
    }

    @PostMapping("/delete")
    @ApiOperation("根据id更新文档内容")
    public ResponseEntity delete(@RequestBody SearchParam param) {
        return service.delete(param);
    }


}

重点来了,Service层,具体实现方法

在service类里,我们需要用到我们之前在config配置类里配置的bean,但是如果直接注入的话,spring会报如下错误

SpringBoot整合ES(REST Client方式)并实现简单的增删改查_第1张图片

意思是spring不知道我们现在用哪个类,对于这个报错,我们做如下处理

@Service
@Slf4j
public class MyService {

    @Qualifier("myClient")
    @Autowired
    private RestClient client;
	
}

用@Qualifier注解来指定具体要注入哪个bean

通过id查询:

    /**
     * 根据id查询文档内容
     *
     * @param param
     * @return
     */
    public JSONObject getDataById(SearchParam param) {
        //拼接查询内容
        String body = param.getIndex() + "/" + param.getType() + "/" + param.getId();
        Request request = new Request("GET", body);
        JSONObject jsonObject = new JSONObject();
        try {
            Response response = client.performRequest(request);
            String responseBody = EntityUtils.toString(response.getEntity(), "UTF-8");
            JSONObject json = JSONObject.parseObject(responseBody);
            //获取我们需要的内容
            Object source = json.get("_source");
            jsonObject = JSONObject.parseObject(source.toString());
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return jsonObject;
    }

添加文档:

    /**
     * 添加文档
     *
     * @param param
     * @return
     */
    public ResponseEntity add(SearchParam param) {
        Person person = new Person();
        person.setName("朱元璋");
        person.setAddr("安徽凤阳");
        person.setBirthday("1328-10-29");
        person.setId("1234567890");
        //以bean的id为该文档的id,以便查询
        String body = param.getIndex() + "/" + param.getType() + "/" + person.getId();
        String responseBody = "";
        try {
            Request request = new Request("POST", body);
            JSONObject jsonObject = (JSONObject) JSONObject.toJSON(person);
            //设置请求体并指定ContentType和编码格式
            request.setEntity(new NStringEntity(jsonObject.toString(), "UTF-8"));
            Response response = client.performRequest(request);
            //获取响应体
            responseBody = EntityUtils.toString(response.getEntity());
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return new ResponseEntity<>(responseBody, HttpStatus.OK);
    }

根据id更新文档内容:

    /**
     * 根据id更新文档内容
     *
     * @param param
     * @return
     */
    public ResponseEntity update(SearchParam param) {
        Person person = new Person();
        person.setName("朱棣");
        person.setAddr("南京");
        person.setBirthday("1360-05-02");
        //需要更新对应的id
        String body = param.getIndex() + "/" + param.getType() + "/" + param.getId() + "/_update";
        String responseBody = "";
        try {
            //构造http请求
            Request request = new Request("POST", body);
            JSONObject json = (JSONObject) JSONObject.toJSON(person);
            JSONObject jsonObject = new JSONObject();
            //将数据由"doc"包住,以便内部识别
            jsonObject.put("doc", json);
            request.setEntity(new NStringEntity(jsonObject.toString(), "UTF-8"));
            Response response = client.performRequest(request);
            //获取响应体
            responseBody = EntityUtils.toString(response.getEntity());
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return new ResponseEntity<>(responseBody, HttpStatus.OK);
    }
 

根据id删除对应文档:

    /**
     * 根据id删除文档
     *
     * @param param
     * @return
     */
    public ResponseEntity delete(SearchParam param) {
        String body = param.getIndex() + "/" + param.getType() + "/" + param.getId();
        String responseBody = "";
        try {
            Request request = new Request("DELETE", body);
            // 执行HTTP请求
            Response response = client.performRequest(request);
            // 获取结果
            responseBody = EntityUtils.toString(response.getEntity());
        } catch (IOException e) {
            log.error(e.getMessage());
        }
        return new ResponseEntity<>(responseBody, HttpStatus.OK);
    }

好了,简单的增删改查已经可以实现了,而且对于增删改这三种操作来说,以上的方法已经基本够用了,但是对于查询的操作,远远不够,比如我不知道文档的id,我需要通过name="张三"这个条件查询出所有符合条件的文档内容来,还有我需要知道出生日期在1990-1991年之间的,如此种种,上述方法不可能实现。

关于复杂查询的,SpringBoot工程整合ElasticSearch(通过Rest-High-Level-Client)并实现较复杂的查询​​​​​​​

 

你可能感兴趣的:(ElasticSearch)