springboot整合ES(Elasticsearch)整合Knife4j

springboot整合ES(Elasticsearch)整合Knife4j

资源下载路径:资源下载路径
该资源包括:elasticsearch的一个简单demo。有elasticsearch的window6.8.1版本。还有elasticsearch-head-master.还有elasticsearch-analysis-ik-5.6.8。还有elasticsearch-analysis-pinyin-6.8.1

ES是比较主流的技术,最近刚学习了下,写个小demo记录下。

搭建es

es下载

ES官网下载地址
https://www.elastic.co/cn/downloads/past-releases#elasticsearch
在这里插入图片描述

注意
配合head使用需要处理下跨域问题
在这里插入图片描述

在配置文件最后加上:

http.cors.enabled: true
http.cors.allow-origin: “*”

启动ES
进入到 D:\elasticsearch6.8\elasticsearch-6.8.1\bin 目录,执行:

elasticsearch

在这里插入图片描述

在这里插入图片描述

启动es成功!

elasticsearch-head-master下载

head-master下载git路径
https://github.com/mobz/elasticsearch-head.git

启动master
进入到 D:\elasticsearch6.8\elasticsearch-head-master 目录,输入:

grunt server

在这里插入图片描述

启动成功!

浏览器访问: http://localhost:9100/
在这里插入图片描述

至此ES搭建成功!
以下是java代码部分

目录结构

在这里插入图片描述

pom文件
<!--elasticsearch-->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-elasticsearch</artifactId>
    <version>3.2.1.RELEASE</version>
</dependency>

<!--knife4j-->
<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-spring-boot-starter</artifactId>
    <!--在引用时请在maven中央仓库搜索最新版本号-->
    <version>2.0.2</version>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
    <scope>provided</scope>
</dependency>
properties配置文件
spring.application.name=es
server.port=2080

# ES配置
elasticsearch.host=127.0.0.1
elasticsearch.port=9300
elasticsearch.clustername=elasticsearch
elasticsearch.search.pool.size=5

ESConfig
package com.zjy.es.config;

import org.elasticsearch.client.Client;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

import java.net.InetAddress;

@Configuration
@EnableElasticsearchRepositories(basePackages = "com.zjy.es.dao")
public class ElasticsearchConfig {
    
    

    /**日志对象*/
    private static final Logger logger = LoggerFactory.getLogger(ElasticsearchConfig.class);

    @Value("${elasticsearch.host}")
    private String esHost;

    @Value("${elasticsearch.port}")
    private int esPort;

    @Value("${elasticsearch.clustername}")
    private String esClusterName;

    @Value("${elasticsearch.search.pool.size}")
    private Integer threadPoolSearchSize;


    @Bean
    public Client client() throws Exception {
    
    
        Settings esSettings = Settings.builder()
                .put("cluster.name", esClusterName)
                //增加嗅探机制,找到ES集群,非集群置为false
                .put("client.transport.sniff", true)
                //增加线程池个数
                .put("thread_pool.search.size", threadPoolSearchSize)
                .build();
        return new PreBuiltTransportClient(esSettings)
                .addTransportAddress(new TransportAddress(InetAddress.getByName(esHost), esPort));
    }

    @Bean(name="elasticsearchTemplate")
    public ElasticsearchOperations elasticsearchTemplateCustom() throws Exception {
    
    
        ElasticsearchTemplate elasticsearchTemplate;
        try {
    
    
            elasticsearchTemplate = new ElasticsearchTemplate(client());
            return elasticsearchTemplate;
        } catch (Exception e) {
    
    
            logger.error("初始化 ElasticsearchTemplate 失败");
            return new ElasticsearchTemplate(client());
        }
    }
}

swaggerConfig
package com.zjy.es.config;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
@EnableKnife4j
public class Swagger2Config {
    
    

    @Bean
    public Docket createRestApi() {
    
    
        return  new Docket(DocumentationType.SWAGGER_2)
                .useDefaultResponseMessages(false)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.zjy.es.controller"))
                .paths(PathSelectors.any())
                .build();

    }

    private ApiInfo apiInfo() {
    
    
        return new ApiInfoBuilder()
                .title("swagger-bootstrap-ui RESTful APIs")
                .description("swagger-bootstrap-ui")
                .termsOfServiceUrl("http://localhost:8999/")
                .version("1.0")
                .build();
    }
}
Controller
package com.zjy.es.controller;

import com.zjy.es.dao.ESRepository;
import com.zjy.es.entity.ESData;
import com.zjy.es.entity.ResultBO;
import io.swagger.annotations.ApiOperation;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.web.bind.annotation.*;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.UUID;

/**
 * ES 入口
 */
@RequestMapping("/user")
@RestController
public class ESController {
    
    

    /**日志对象*/
    private static final Logger logger = LoggerFactory.getLogger(ESController.class);

    @Autowired
    private ESRepository esRepository;

    /**
     * 添加多条es数据
     * @param esDataList
     * @return
     */
    @ApiOperation(value = "保存es数据", notes = "保存es数据")
    @PostMapping("save")
    public ResultBO save(@RequestBody List<ESData> esDataList){
    
    

        logger.info("接收到的 ES 数据为: {},总共是 {} 条数据", esDataList, esDataList.size());
        for (ESData esData : esDataList) {
    
    
            String id = UUID.randomUUID().toString().replaceAll("-", "");
            esData.setId(id);
            esData.setCreateTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            esData.setSortTime(System.currentTimeMillis());
        }
        esRepository.saveAll(esDataList);
        logger.info("保存数据成功!");

        return ResultBO.success(esDataList);
    }

    /**
     * 查询es数据
     * @param id
     * @return
     */
    @ApiOperation(value = "查询es数据", notes = "查询es数据")
    @GetMapping("detail")
    public ResultBO detail(@RequestParam(value = "id", required = true) String id){
    
    

        logger.info("接收到的 ES 的id为: {}", id);

        Optional<ESData> byId = esRepository.findById(id);
        logger.info("查询到的 ES数据 为: {}", byId);

        return ResultBO.success(byId);
    }

    /**
     * 查询所有es数据
     * @return
     */
    @ApiOperation(value = "查询所有es数据", notes = "查询所有es数据")
    @GetMapping("list")
    public ResultBO list(){
    
    

        logger.info("查询所有es数据");

        Iterable<ESData> all = esRepository.findAll();
        logger.info("查询到的 所有ES数据 为: {}", all);

        return ResultBO.success(all);
    }

    /**
     * 根据关键字 title 中进行搜索
     * @return
     */
    @ApiOperation(value = "根据关键字 title 中进行搜索", notes = "据关键字 title 中进行搜索")
    @GetMapping("findByTitle")
    public ResultBO findByTitle(@RequestParam(value = "title", required = true) String title){
    
    

        logger.info("输入的关键字 title 为: {}", title);

        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", title);
        Iterable<ESData> search = esRepository.search(matchQueryBuilder);
        logger.info("查询到的 所有ES数据 为: {}", search);

        return ResultBO.success(search);
    }

    /**
     * 根据关键字 title 中进行分页查询排序
     * @return
     */
    @ApiOperation(value = "根据关键字 title 中进行分页搜索", notes = "根据关键字 title 中进行分页搜索")
    @PostMapping("findByTitlePage")
    public ResultBO findByTitlePage(@RequestParam(value = "title", required = true) String title, Integer page, Integer size){
    
    

        logger.info("输入的关键字 title 为: {}, paget为: {}, size为: {}", title, page, size);
        // 根据创建时间 倒排序 并分页
        Sort sort = Sort.by("sortTime").descending();
        Pageable pageable = PageRequest.of(page, size, sort);
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", title);
        Iterable<ESData> search = esRepository.search(matchQueryBuilder, pageable);
        logger.info("查询到的 所有ES数据 为: {}", search);

        return ResultBO.success(search);
    }

    /**
     * 根据id进行删除
     * @return
     */
    @ApiOperation(value = "根据id进行删除", notes = "根据id进行删除")
    @PostMapping("delete")
    public ResultBO delete(@RequestParam(value = "id", required = true) String id){
    
    

        logger.info("要删除的 id 为: {}", id);

        esRepository.deleteById(id);
        logger.info("成功删除es");

        return ResultBO.success();
    }

    /**
     * 删除所有
     * @return
     */
    @ApiOperation(value = "删除所有", notes = "删除所有")
    @PostMapping("deleteAll")
    public ResultBO deleteAll(){
    
    

        logger.info("删除所有");

        esRepository.deleteAll();
        logger.info("成功删除所有ES数据");

        return ResultBO.success();
    }
}

ESRepository
package com.zjy.es.dao;

import com.zjy.es.entity.ESData;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface ESRepository extends ElasticsearchRepository<ESData, String> {
    
    

}

ESData
package com.zjy.es.entity;

import lombok.Data;
import lombok.ToString;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

@Data
@ToString
@Document(indexName = "blog", type = "article")
public class ESData {
    
    

    /**
     * 主键ID
     */
    @Field(type = FieldType.Keyword)
    private String id;

    /**
     * 文章标题
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String title;

    /**
     * 文章内容
     */
    @Field(type = FieldType.Text, analyzer = "ik_max_word", searchAnalyzer = "ik_max_word")
    private String content;

    /**
     * 创建时间
     */
    @Field(type = FieldType.Date, pattern = "yyyy-MM-dd HH:mm:ss", format = DateFormat.custom, fielddata = true)
    private String createTime;

    /**
     * 创建时间--排序使用
     */
    @Field(type = FieldType.Long, fielddata = true)
    private long sortTime;
}

注意:fielddata = true 比较耗堆内存

ResultBO
package com.zjy.es.entity;

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
public class ResultBO<T> {
    
    

    @ApiModelProperty(required = true, notes = "返回数据")
    private T content;

    @ApiModelProperty(required = true, notes = "返回成功与否", example = "true")
    private boolean succeed = true;

    @ApiModelProperty(required = true, notes = "结果码", example = "200")
    private int code = 0;

    @ApiModelProperty(required = true, notes = "返回信息说明", example = "SUCCESS")
    private String msg;

    public ResultBO(T content) {
    
    
        this.content = content;
    }

    public ResultBO(boolean succeed, int code, String msg, T content) {
    
    
        this.succeed = succeed;
        this.code = code;
        this.msg = msg;
        this.content = content;
    }

    public ResultBO(boolean succeed, int code, String msg) {
    
    
        this.succeed = succeed;
        this.code = code;
        this.msg = msg;
    }

    public ResultBO() {
    
    

    }

    public static <T> ResultBO<T> success(T content) {
    
    
        return new ResultBO<T>(content);
    }

    public static ResultBO success() {
    
    
        return new ResultBO();
    }

    public static ResultBO fail(int code, String msg) {
    
    
        return new ResultBO(false, code, msg);
    }

    public static ResultBO fail(String msg) {
    
    
        return new ResultBO(false, -1, msg);
    }

    public static ResultBO fail() {
    
    
        return fail("fail");
    }
}

代码贴完了。开始测试

测试

访问swagger: http://localhost:2080/doc.html#

新增

在这里插入图片描述

新增了3条数据
控制台打印:
在这里插入图片描述

ES:
在这里插入图片描述

测试OK!

模糊查询

在这里插入图片描述

在这里插入图片描述

控制台打印结果:
在这里插入图片描述

测试OK!

删除

在这里插入图片描述

在这里插入图片描述

删除了一条数据
测试OK!

分页查询排序

在这里插入图片描述

page是从0开始
在这里插入图片描述

测试OK!


这里是es身份验证的方法

es配置
1.在elasticsearch.yml最后添加

http.cors.allow-headers: Authorization
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true

在这里插入图片描述

2.设置ES密码

进入到 D:\zhoujunyi10\Downloads\elasticsearch-6.8.1\bin 目录下执行:

elasticsearch-setup-passwords interactive

在这里插入图片描述

会输入好多个密码。ES密码的级别:elastic, kibana, logstashsystem,beats_system
挨个设置就好

3.修改项目application.properties配置文件

添加用户名和密码配置

spring.application.name=es
server.port=2080

# ES配置
elasticsearch.host=127.0.0.1
elasticsearch.port=9200
elasticsearch.clustername=elasticsearch
elasticsearch.search.pool.size=5
elasticsearch.username=elastic
elasticsearch.password=123456
4.修改ElasticsearchConfig类

上部分注释掉的是之前使用的(没有身份认证的ES)
下部分是使用身份认证的API

package com.zjy.es.config;

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.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.TransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

import java.net.InetAddress;

@Configuration
@EnableElasticsearchRepositories(basePackages = "com.zjy.es.dao")
public class ElasticsearchConfig {
    
    

    /**日志对象*/
    private static final Logger logger = LoggerFactory.getLogger(ElasticsearchConfig.class);

    @Value("${elasticsearch.host}")
    private String esHost;

    @Value("${elasticsearch.port}")
    private int esPort;

    @Value("${elasticsearch.clustername}")
    private String esClusterName;

    @Value("${elasticsearch.search.pool.size}")
    private Integer threadPoolSearchSize;

    @Value("${elasticsearch.username}")
    private String userName;

    @Value("${elasticsearch.password}")
    private String password;

//    @Bean
//    public Client client() throws Exception {
    
    
//        Settings esSettings = Settings.builder()
//                .put("cluster.name", esClusterName)
//                //增加嗅探机制,找到ES集群,非集群置为false
//                .put("client.transport.sniff", true)
//                //增加线程池个数
//                .put("thread_pool.search.size", threadPoolSearchSize)
//                .build();
//        return new PreBuiltTransportClient(esSettings)
//                .addTransportAddress(new TransportAddress(InetAddress.getByName(esHost), esPort));
//    }

//    @Bean(name="elasticsearchTemplate")
//    public ElasticsearchOperations elasticsearchTemplateCustom() throws Exception {
    
    
//        ElasticsearchTemplate elasticsearchTemplate;
//        try {
    
    
//            elasticsearchTemplate = new ElasticsearchTemplate(client());
//            return elasticsearchTemplate;
//        } catch (Exception e) {
    
    
//            logger.error("初始化 ElasticsearchTemplate 失败");
//            return new ElasticsearchTemplate(client());
//        }
//    }

    @Bean
    public RestHighLevelClient client(){
    
    
        /*用户认证对象*/
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        /*设置账号密码*/
        credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials(userName, password));
        /*创建rest client对象*/
        RestClientBuilder builder = RestClient.builder(new HttpHost(esHost, esPort))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
    
    
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
    
    
                        return httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                    }
                });
        RestHighLevelClient client = new RestHighLevelClient(builder);
        return client;
    }

    @Bean(name="elasticsearchTemplate")
    public ElasticsearchRestTemplate elasticsearchRestTemplate(){
    
    
        return new ElasticsearchRestTemplate(client());
    }

}

至此修改完成。可以测试了
输错密码,或者不输密码访问请求:
提示身份认证不过
在这里插入图片描述

输入正确的用户名和密码:
在这里插入图片描述

测试OK!


补充:
这里补充下,根据正文(或者叫内容)的关键词搜索。他内部是使用分词器,所以得使用个词来搜索

pom文件:

<!--fastjson-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.47</version>
</dependency>

java代码:

    /**
     * 根据关键字 content 中进行搜索
     * @return
     */
    @ApiOperation(value = "根据关键字 content 中的词进行搜索", notes = "据关键字 content 中进行搜索")
    @GetMapping("findByContent")
    public ResultBO findByContent(@RequestParam(value = "content", required = true) String content){
    
    

        logger.info("输入的关键字 content 为: {}", content);

        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("content", content);
        Iterable<ESData> search = esRepository.search(matchQueryBuilder);
        Object json = JSONArray.toJSON(search);
        logger.info("查询到的 所有ES数据 为: {}", json);

        return ResultBO.success(search);
    }

在这里插入图片描述

在这里插入图片描述

欢迎大神指导,可以留言交流!

======================
本人原创文章,转载注明出入!

=================

猜你喜欢

转载自blog.csdn.net/dayonglove2018/article/details/107432760