配置文件
(pom.xml):
<!--jar包版本-->
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.9.3</elasticsearch.version>
<hutu.version>4.6.1</hutu.version>
<springSwagger.version>2.6.1</springSwagger.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<!-- 第三方util -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutu.version}</version>
</dependency>
<!-- 接口文檔生成 -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springSwagger.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springSwagger.version}</version>
</dependency>
</dependencies>
(application.yml):
server: port: 9000 spring: main: allow-bean-definition-overriding: true basePackage: com.karat.es resources: static-locations: classpath:/static, classpath:/templates jackson: #參數意義: #JsonInclude.Include.ALWAYS 默認 #JsonInclude.Include.NON_DEFAULT 屬性為默認值不序列化 #JsonInclude.Include.NON_EMPTY 屬性為 空(””) 或者為 NULL 都不序列化 #JsonInclude.Include.NON_NULL 屬性為NULL 不序列化 default-property-inclusion: ALWAYS time-zone: GMT+8 date-format: yyyy-MM-dd HH:mm:ss elasticsearch: hosts: 127.0.0.1 #集群地址,多個用,隔開 port: 9200 # 使用的端口號 schema: http #使用的協議 connectTimeOut: 1000 #連接超時時間 socketTimeOut: 30000 #連接超時時間 connectionRequestTimeOut: 500 #獲取連接的超時時間 maxConnectNum: 100 #最大連接數 maxConnectPerRoute: 100 #最大路由連接數 preStr: es_test_ swagger2: open: true testToken: Get after landing basePackage: ${spring.basePackage} name: url: email: title: springboot利用swagger構建api文檔 description: springboot利用swagger構建api文檔
配置類
(EsConfig.java):
import lombok.Getter; import lombok.Setter; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @ConfigurationProperties(prefix = "elasticsearch", ignoreInvalidFields = true) @Getter @Setter @Component public class EsConfig { private String hosts; private int port; private String schema; private int connectTimeOut; private int socketTimeOut; private int connectionRequestTimeOut; private int maxConnectNum; private int maxConnectPerRoute; private String preStr; }
(EsConfiguration.java):
import org.apache.http.HttpHost; import org.apache.http.client.config.RequestConfig.Builder; import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback; import org.elasticsearch.client.RestClientBuilder.RequestConfigCallback; import org.elasticsearch.client.RestHighLevelClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.Resource; @Configuration public class EsConfiguration { @Resource EsConfig config; @Bean public RestHighLevelClient client() { RestClientBuilder builder = RestClient.builder(new HttpHost(config.getHosts(),config.getPort(),config.getSchema())); // 異步httpclient連接延時配置 builder.setRequestConfigCallback(new RequestConfigCallback() { @Override public Builder customizeRequestConfig(Builder requestConfigBuilder) { requestConfigBuilder.setConnectTimeout(config.getConnectTimeOut()); requestConfigBuilder.setSocketTimeout(config.getSocketTimeOut()); requestConfigBuilder.setConnectionRequestTimeout(config.getConnectionRequestTimeOut()); return requestConfigBuilder; } }); // 異步httpclient連接數配置 builder.setHttpClientConfigCallback(new HttpClientConfigCallback() { @Override public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) { httpClientBuilder.setMaxConnTotal(config.getMaxConnectNum()); httpClientBuilder.setMaxConnPerRoute(config.getMaxConnectPerRoute()); return httpClientBuilder; } }); RestHighLevelClient client = new RestHighLevelClient(builder); return client; } }
存儲對象
(EsBean.java):
import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import java.util.Date; @Data public class EsBean { private String id; private String name; private int age; private String phone; @JsonFormat( pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8" ) protected Date createTime; }
(PageEsBean.java):
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import lombok.Data; import java.util.Date; @Data @JsonIgnoreProperties(ignoreUnknown = true) public class PageEsBean extends EsBean{ //每頁大小 private int pageSize=1; //當前頁 private int pageNum=3; //結束范圍時間段 @JsonFormat( pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8" ) protected Date endTime; //開始范圍時間段 @JsonFormat( pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8" ) protected Date beginTime; }
Es服務
(RestHighLevelClientService.java):
import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; import com.karat.es.bean.EsBean; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.action.delete.DeleteRequest; import org.elasticsearch.action.delete.DeleteResponse; import org.elasticsearch.action.get.GetRequest; import org.elasticsearch.action.get.GetResponse; import org.elasticsearch.action.index.IndexRequest; import org.elasticsearch.action.index.IndexResponse; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateResponse; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.indices.CreateIndexRequest; import org.elasticsearch.client.indices.CreateIndexResponse; import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.IOException; import java.util.ArrayList; import java.util.List; @Service @Slf4j public class RestHighLevelClientService { @Resource private RestHighLevelClient client; @Value("${elasticsearch.preStr}") private String preStr; /** * 獲取索引 * @param beanClass * @return */ public String getIndex(Class beanClass) { return preStr + StrUtil.toUnderlineCase(beanClass.getSimpleName()).toLowerCase(); } /** * 創建索引 * @param index 索引名稱 * @throws IOException */ public void createIndex(String index) throws IOException { CreateIndexRequest request = new CreateIndexRequest(index); CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT); log.info("創建索引: {}", JSONUtil.toJsonStr(createIndexResponse)); } /** * 判斷索引是否存在 * @param index 索引名稱 * @return * @throws IOException */ public boolean existsIndex(String index) throws IOException { GetIndexRequest request = new GetIndexRequest(); request.indices(index); boolean exists = client.indices().exists(request, RequestOptions.DEFAULT); log.info("判斷索引是否存在: {}",exists); return exists; } /** * 增加記錄 * @param esBean 數據 * @throws IOException */ public boolean insert(EsBean esBean) throws IOException { String index = getIndex(esBean.getClass()); IndexRequest indexRequest = new IndexRequest(index);// 創建索引請求對象 indexRequest.id(esBean.getId()); indexRequest.source(JSONUtil.toJsonStr(esBean), XContentType.JSON);// 設置文檔內容 IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);// 執行增加文檔 log.info("增加記錄:{},狀態碼:{}",JSONUtil.toJsonStr(response),response.status().getStatus()); if (!exists(index, esBean.getId())) { log.error("文檔不存在: {}, 行號:{}", esBean.getId(), new Throwable().getStackTrace()[0].getLineNumber()); return false; }else{ return true; } } /** * 判斷記錄是都存在 * @param index 索引名稱 * @param id 數據ID主鍵 * @return * @throws IOException */ public boolean exists(String index, String id) throws IOException { GetRequest getRequest = new GetRequest(index, id); boolean exists = client.exists(getRequest, RequestOptions.DEFAULT); log.info("判斷記錄是都存在: {}",exists); return exists; } /** * 獲取記錄信息 * @param id 記錄主鍵ID * @param beanClass 獲取數據Bean對象 * @throws IOException */ public <T> T get(String id,Class<T> beanClass) throws Exception { T t = beanClass.newInstance(); //查看索引 String index = getIndex(beanClass); if (!exists(index, id)) { log.error("文檔不存在: {}, 行號:{}", id, new Throwable().getStackTrace()[0].getLineNumber()); return null; } //單條查詢 GetRequest getRequest = new GetRequest(index, id); GetResponse response = client.get(getRequest, RequestOptions.DEFAULT); log.info("獲取記錄信息: 索引:{},Id:{}",response.getIndex(),response.getId()); // 將 JSON 轉換成對象 if (response.isExists()) { t = JSONUtil.toBean(response.getSourceAsString(), beanClass); } return t; } /** * 更新記錄信息 * @param esBean 數據 * @throws IOException */ public boolean update(EsBean esBean){ try { String index = getIndex(esBean.getClass()); if (!existsIndex(index)) { log.error("索引不存在: {}, 行號:{}", index, new Throwable().getStackTrace()[0].getLineNumber()); return false; } if (!exists(index, esBean.getId())) { log.error("文檔不存在: {}, 行號:{}", esBean.getId(), new Throwable().getStackTrace()[0].getLineNumber()); return false; } UpdateRequest request = new UpdateRequest(index, esBean.getId());// 創建索引請求對象 request.doc(JSONUtil.toJsonStr(esBean), XContentType.JSON);// 設置更新文檔內容 UpdateResponse response = client.update(request, RequestOptions.DEFAULT);// 執行更新文檔 log.info("更新記錄信息: {},狀態碼:{}",JSONUtil.toJsonStr(response),response.status()); return RestStatus.OK.equals(response.status()); }catch (Exception e){ e.printStackTrace(); return false; } } /** * 刪除記錄 * @param beanClass 刪除對象 * @param id 索引數據ID * @throws IOException */ public boolean delete(String id,Class beanClass) throws IOException { String index = getIndex(beanClass); if (!existsIndex(index)) { log.error("索引不存在: {}, 行號:{}", index, new Throwable().getStackTrace()[0].getLineNumber()); return false; } if (!exists(index, id)) { log.error("文檔不存在: {}, 行號:{}", id, new Throwable().getStackTrace()[0].getLineNumber()); return false; } DeleteRequest deleteRequest = new DeleteRequest(index, id); DeleteResponse response = client.delete(deleteRequest, RequestOptions.DEFAULT); log.info("刪除記錄: {}",JSONUtil.toJsonStr(response)); return RestStatus.OK.equals(response.status()); } /** * 搜索 * 自定義條件查詢,多條文檔 * @param searchSourceBuilder 構建查詢條件(注意:termQuery 支持多種格式查詢,如 boolean、int、double、string 等,這里使用的是 string 的查詢) * @param beanClass * @throws IOException */ public <T> List<T> search(SearchSourceBuilder searchSourceBuilder, Class<T> beanClass) { try { String index = getIndex(beanClass); if (!existsIndex(index)) { log.error("索引不存在: {}, 行號:{}", index, new Throwable().getStackTrace()[0].getLineNumber()); return new ArrayList<>(); } SearchRequest searchRequest = new SearchRequest(index); searchRequest.source(searchSourceBuilder); SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT); log.info("搜索:{}-狀態:{}-總條數:{}",JSONUtil.toJsonStr(response),response.status(),response.getHits().getTotalHits().value); if (RestStatus.OK.equals(response.status()) && response.getHits().getHits().length > 0) { SearchHits hits = response.getHits(); List<T> list = new ArrayList<>(); for (SearchHit hit : hits) { // 將 JSON 轉換成對象 T t = JSONUtil.toBean(hit.getSourceAsString(), beanClass); // 輸出查詢信息 list.add(t); } return list; } return null; }catch (Exception e){ e.printStackTrace(); return null; } } }
import com.karat.es.bean.EsBean; import com.karat.es.bean.PageEsBean; import com.karat.es.service.RestHighLevelClientService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.sort.SortOrder; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.Date; import java.util.List; import java.util.UUID; @Slf4j @RestController @RequestMapping(value = "es") @Api(value = "EsController", description = "es測試", produces = MediaType.APPLICATION_JSON_VALUE) public class RestHighLevelClientController { @Resource RestHighLevelClientService restHighLevelClientService; @RequestMapping(value = "add", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation(value = "增", httpMethod = "POST", notes = "add") public boolean add(@RequestBody EsBean esBean)throws Exception{ esBean.setId(UUID.randomUUID().toString()); esBean.setCreateTime(new Date()); return restHighLevelClientService.insert(esBean); } @RequestMapping(value = "del", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation(value = "刪", httpMethod = "GET", notes = "del") public boolean del(@RequestParam("id")String id) throws Exception{ return restHighLevelClientService.delete(id,EsBean.class); } @RequestMapping(value = "update", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation(value = "改", httpMethod = "POST", notes = "update") public boolean update(@RequestBody EsBean esBean){ esBean.setCreateTime(new Date()); return restHighLevelClientService.update(esBean); } @RequestMapping(value = "get", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation(value = "查", httpMethod = "GET", notes = "get") public EsBean test(@RequestParam("id")String id) throws Exception{ return restHighLevelClientService.get(id,EsBean.class); } @RequestMapping(value = "search", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE) @ApiOperation(value = "多條件查詢", httpMethod = "POST", notes = "search") public List search(@RequestBody PageEsBean pageEsBean){ // 構建查詢條件 BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery(); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); //多條件設置 if(!pageEsBean.getName().equals("")){ boolBuilder.must(QueryBuilders.matchPhraseQuery("name" ,pageEsBean.getName())); } if(pageEsBean.getAge()!=0){ boolBuilder.must(QueryBuilders.matchPhraseQuery("age" ,pageEsBean.getAge())); } //時間段查詢 if(pageEsBean.getBeginTime()!=null&&pageEsBean.getEndTime()!=null){ boolBuilder.must(QueryBuilders.rangeQuery("createTime").gte(pageEsBean.getBeginTime().getTime()).lte(pageEsBean.getEndTime().getTime())); } //分頁從0開始 設置從第幾條開始查詢 searchSourceBuilder.from((pageEsBean.getPageNum()-1)*pageEsBean.getPageSize()).size(pageEsBean.getPageSize()); // 倒序 searchSourceBuilder.sort("createTime", SortOrder.DESC); //trackTotalHits(true) 設置查詢索引中數據總條數 searchSourceBuilder.trackTotalHits(true); searchSourceBuilder.query(boolBuilder); return restHighLevelClientService.search(searchSourceBuilder,new EsBean().getClass()); } }
Demo目錄結構: