配置文件
(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目录结构: