說明
- springboot版本為2.5.0
- jdk版本為1.8
- 本人在項目中集成了swagger2
參考了一個B站上的視頻:https://www.bilibili.com/video/BV13v41177Fu
本人把項目放到了gitee上:https://gitee.com/guoanhao/aoh-eslog.git
核心依賴
<!-- spring data elasticsearch --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency>
本人的pom.xml

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>aoh-eslog</artifactId> <version>1.0-SNAPSHOT</version> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!-- spring data elasticsearch --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> </dependency> <!-- swagger2 --> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <!-- swagger2換膚 --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>swagger-bootstrap-ui</artifactId> <version>1.9.6</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.yml
在yml文件中配置elasticsearchip和端口號(集群的話用逗號分割就可以了)
server: port: 8080 # servlet: # context-path: /com/gah/service spring: elasticsearch: rest: uris: http://192.168.186.142:9200 # uris: http://192.168.186.142:9200,http://192.168.186.142:9200,http://192.168.186.142:9200 # 隊列實體類路徑配置,以便通過java反射來獲取實體類 pojo.path: com.nsccjn.aoh.eslog.pojo.
本人的實體類,測試類
package com.nsccjn.aoh.eslog.pojo; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; /** * 測試 */ @Data @Document(indexName = "test",createIndex = false) public class Text { @Id private Integer id; @Field(type = FieldType.Text) private String name; @Field(type = FieldType.Integer) private Integer age; public Text() { } public Text(Integer id, String name, Integer age) { this.id = id; this.name = name; this.age = age; } }
下面這個的實體類叫做Index(對應的elasticsearch的索引名稱是test)
測試類中使用的是這個實體類
由於索引名和實體類名稱不對應,所以下面的controller中沒法通過前台傳參的方式獲取並與elasticsearch的索引相對應(可以用Text實體類傳參)
package com.nsccjn.aoh.eslog.pojo; import lombok.Data; import org.springframework.data.annotation.Id; import org.springframework.data.elasticsearch.annotations.Document; import org.springframework.data.elasticsearch.annotations.Field; import org.springframework.data.elasticsearch.annotations.FieldType; /** * 測試 */ @Data @Document(indexName = "test",createIndex = false) public class Index { @Id private Integer id; @Field(type = FieldType.Text) private String name; @Field(type = FieldType.Integer) private Integer age; public Index() { } public Index(Integer id, String name, Integer age) { this.id = id; this.name = name; this.age = age; } }
下面是測試類

import com.nsccjn.aoh.eslog.Application; import com.nsccjn.aoh.eslog.dao.IndexRepository; import com.nsccjn.aoh.eslog.dao.JobsRepository; import com.nsccjn.aoh.eslog.pojo.Index; import com.nsccjn.aoh.eslog.pojo.Jobs; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.IndexOperations; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.document.Document; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import java.util.ArrayList; import java.util.List; @SpringBootTest(classes = Application.class) public class ESLogTest { @Autowired private ElasticsearchRestTemplate template; @Autowired private JobsRepository jobsRepository; @Autowired private IndexRepository indexRepository; @Value("${pojo.path}") String POJO_PATH; /** * 新增索引 */ @Test public void testIndex() { // 獲取索引對象 IndexOperations indexOperations = template.indexOps(Test.class); // 創建索引 indexOperations.create(); // 獲取映射 Document mapping = indexOperations.createMapping(Test.class); // 將映射放入索引 indexOperations.putMapping(mapping); // 判斷映射是否存在 boolean exists = indexOperations.exists(); System.out.printf(String.valueOf(exists)); // Map<String, Object> mapping = indexOperations.getMapping(); // System.out.printf(String.valueOf(mapping)); } @Test public void testRepository() { // 添加 // List<Index> list = new ArrayList<>(); // list.add(new Index(10, "李清照", 26)); // list.add(new Index(11, "辛稼軒", 20)); // indexRepository.saveAll(list); // indexRepository.deleteAll(); // 根據名稱查詢歷史名人 // List<Index> indexList = indexRepository.findByName("%李%"); // System.out.printf(String.valueOf(indexList)); // 自定義規則查詢 Index index = indexRepository.findByIdValue(10); System.out.printf(String.valueOf(index)); } /** * 增刪改 */ @Test public void testCUD() { // 添加(id存在則更新) List<Index> list = new ArrayList<>(); list.add(new Index(12, "蘇子瞻", 26)); list.add(new Index(13, "王陽明", 20)); // template.save(list); // 刪除test索引中id為11的數據 template.delete("11", IndexCoordinates.of("test")); } /** * 查詢 */ @Test public void testSearch() { String startTime = "2021-07-20T14:20:00.000Z"; String endTime = "2021-07-21T17:14:43.000Z"; // 分頁 Pageable pageable = PageRequest.of(0, 10); // 查詢字段是name值是’李清照‘的數據 NativeSearchQuery query = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.boolQuery() .must(QueryBuilders.matchQuery("jobname","大家好")) .must(QueryBuilders.rangeQuery("@timestamp").gte(startTime).lte(endTime)) ) .withSort(SortBuilders.fieldSort("@timestamp").order(SortOrder.ASC)) .withPageable(pageable) .build(); // path = "com.nsccjn.aoh.eslog.pojo.Jobs"; POJO_PATH += "JobsTime"; Class clazz = null; try { clazz = Class.forName(POJO_PATH); } catch (ClassNotFoundException e) { e.printStackTrace(); } // 指定要查詢的實體類 // SearchHits<Jobs> search = template.search(query, Jobs.class); SearchHits<Jobs> search = template.search(query, clazz); System.out.println(search.getTotalHits()); search.getSearchHits().forEach(System.out::println); } /** * 測試將查詢條件拿出來定義 */ @Test public void testSearch2() { String startTime = "2021-07-18T16:07:00.000Z"; String endTime = "2021-07-21T17:07:00.000Z"; Pageable pageable = PageRequest.of(0, 3); BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); // queryBuilder.must(QueryBuilders.matchQuery("jobName", "大家好")); queryBuilder.must(QueryBuilders.rangeQuery("@timestamp").gte(startTime).lte(endTime)); // 查詢字段是name值是’李清照‘的數據 NativeSearchQuery query = new NativeSearchQueryBuilder() .withQuery(QueryBuilders.boolQuery().must(queryBuilder)) .withSort(SortBuilders.fieldSort("@timestamp").order(SortOrder.ASC)) .withPageable(pageable) .build(); NativeSearchQueryBuilder query2 = new NativeSearchQueryBuilder(); // .withQuery(QueryBuilders.boolQuery().must(queryBuilder)) // .withSort(SortBuilders.fieldSort("@timestamp").order(SortOrder.ASC)) query2.withQuery(queryBuilder); query2.withPageable(pageable); new NativeSearchQueryBuilder(); // NativeSearchQuery query = new NativeSearchQueryBuilder() // .withQuery(QueryBuilders.boolQuery() // .must(QueryBuilders.matchQuery("jobname", "大家好")) // .must(QueryBuilders.rangeQuery("@timestamp").gte(startTime).lte(endTime))) // // .withSort(SortBuilders.fieldSort("@timestamp").order(SortOrder.ASC)) // // .withPageable(pageable) // .build(); // 指定要查詢的實體類 SearchHits<Jobs> search = template.search(query2.build(), Jobs.class); System.out.println(search.getTotalHits()); search.getSearchHits().forEach(System.out::println); } /** * 測試反射獲取實體類 * @throws ClassNotFoundException */ @Test public void test() throws ClassNotFoundException { String path = "com.nsccjn.aoh.eslog.pojo.Jobs"; Class clazz = Class.forName(path); // 獲取類名 // String strName01 = clazz.getName();// 獲取完整類名com.sg.myReflection.bean.User // String strName02 = clazz.getSimpleName();// 直接獲取類名 User // System.out.printf(strName01); // System.out.println(c2); } }
Chrome瀏覽器有一個elasticsearch的插件,如下
到此基本就結束了,不過本人又修改了一下部分代碼(在controller中改的)
通過java反射的方式獲取實體類,就可以在前台傳相應的index(對應實體類名稱)然后后返回相應的結果

package com.nsccjn.aoh.eslog.controller; import com.nsccjn.aoh.eslog.pojo.Jobs; import io.netty.util.internal.StringUtil; import io.swagger.annotations.*; import lombok.SneakyThrows; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.sort.SortBuilders; import org.elasticsearch.search.sort.SortOrder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.query.NativeSearchQuery; import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @Api(value = "ESlog接口", tags = {"獲取ESlog信息接口"}) @RestController public class ESLogController { @Autowired private ElasticsearchRestTemplate template; @Value("${pojo.path}") String POJO_PATH; @GetMapping("/hel") public String hello() { return "李清照"; } /** * 獲取elasticsearch中的日志 * * @param startTime 開始時間 * @param endTime 結束時間 * @param queue 隊列 * @param key 關鍵字 * @param fieldName 關鍵字對應的要查詢的字段 * @param page 當前頁 * @param size 一頁顯示多少條數據 */ @ApiOperation(value = "查詢ESlog信息", notes = "查詢ESlog信息", httpMethod = "GET", produces = "multipart/form-data") @GetMapping("/queryESlog") @ApiImplicitParams({ @ApiImplicitParam(name = "startTime", value = "開始時間", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "endTime", value = "結束時間", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "queue", value = "隊列名稱", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "key", value = "關鍵字", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "fieldName", value = "要查詢的字段名稱", dataType = "String", paramType = "query"), @ApiImplicitParam(name = "page", value = "當前頁", dataType = "Integer", paramType = "query"), @ApiImplicitParam(name = "size", value = "一頁顯示多少條數據", dataType = "Integer", paramType = "query") }) public Object queryESlog(String startTime, String endTime, String queue, String key, String fieldName, Integer page, Integer size) { BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); // 查詢字段是fieldName,值是’key‘的數據 if (!StringUtil.isNullOrEmpty(key) && !StringUtil.isNullOrEmpty(fieldName)) { queryBuilder.must(QueryBuilders.matchQuery(fieldName, key)); } // 時間范圍查詢 if (!StringUtil.isNullOrEmpty(startTime) && !StringUtil.isNullOrEmpty(endTime)) { queryBuilder.must(QueryBuilders.rangeQuery("@timestamp").gte(startTime).lte(endTime)); } // 創建NativeSearchQueryBuilder NativeSearchQueryBuilder query = new NativeSearchQueryBuilder(); query.withQuery(queryBuilder); // 分頁查詢 if (page != null && size != null) { Pageable pageable = PageRequest.of(page, size); query.withPageable(pageable); } // 默認按照時間倒序排序 // query.withSort(SortBuilders.fieldSort("@timestamp").order(SortOrder.DESC)); query.withSort(SortBuilders.fieldSort("id").order(SortOrder.DESC)); try { // 通過反射的方式獲取類對象 Class clazz = Class.forName(POJO_PATH + queue); // 查詢 SearchHits<Jobs> search = template.search(query.build(), clazz); // search.getSearchHits().forEach(System.out::println); return search; } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } }
本人集成了swagger2,相應的代碼如下,依賴在上面給出了,swagger2配置類如下

package com.nsccjn.aoh.eslog.config; 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.service.Contact; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; /** * swagger2配置文件 * http://localhost:8088/swagger-ui.html 原路徑 * http://localhost:8088/doc.html 換膚之后的路徑 */ @Configuration @EnableSwagger2 public class Swagger2 { //api接口包掃描路徑 public static final String SWAGGER_SCAN_BASE_PACKAGE = "com.nsccjn.aoh.eslog.controller"; public static final String VERSION = "1.0.0"; @Bean public Docket createRestApi() { return new Docket(DocumentationType.SWAGGER_2) // 指定API類型為SWAGGER_2 .apiInfo(apiInfo()) // 定義API文檔匯總信息 .select() .apis(RequestHandlerSelectors .basePackage(SWAGGER_SCAN_BASE_PACKAGE)) // 指定controller包,用於生成api的controller包 .paths(PathSelectors.any()) // 可以根據url路徑設置哪些請求加入文檔,忽略哪些請求 .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("ESLog服務平台") //設置文檔的標題 .contact(new Contact("易算平台", "http://localhost:8080/hel", "")) .description("ESLog服務平台 API 接口文檔") // 設置文檔的描述 .version(VERSION) // 設置文檔的版本信息-> 1.0.0 Version information .termsOfServiceUrl("http://www.baidu.com") // 設置文檔的License信息->1.3 License information .build(); } }
經過測試@ApiParam注解不好用,於是就換成了@ApiImplicitParams和@ApiImplicitParam。使用@ApiParam時前台傳的值不能為空,為空就報錯。
我們使用了swagger2換膚,路徑如下
http://localhost:8080/swagger-ui.html 原路徑 http://localhost:8080/doc.html 換膚之后的路徑
調試頁面
查詢結果