1. SpringBoot 版本:3.2.3
elasticsearch-java 版本:8.10.4
jdk: 17
elasticsearch 数据库版本:7.6.2
2.. 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>com.wjh</groupId>
<artifactId>elasticsearch</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>2023.0.0</spring-cloud.version>
<spring.cloud.alibaba.version>2022.0.0.0</spring.cloud.alibaba.version>
<jackson.version>2.16.1</jackson.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 请求参数校验 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<!-- mybatis-plus 分页插件 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.5</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.21</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
<!-- Redis -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.27.1</version>
</dependency>
<!-- ElasticSearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
<!-- Http -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.47</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.26</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.13.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<!-- 接口文档 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<!--<version>2.6.7</version>-->
<configuration>
<!--<fork>true</fork>-->
<classifier>exec</classifier>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
<configuration>
<!-- 跳过单元测试 -->
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
</plugins>
</build>
</project>
3. application.yml
server:
port: 8056
servlet:
context-path: /
spring:
application:
name: elasticsearch
profiles:
active: dev # 环境设置:dev、test、prod
mybatis:
mapper-locations: classpath*:mapper/*Mapper.xml
type-aliases-package: com.wjh.entity
configuration:
map-underscore-to-camel-case: true # 开启驼峰命名法
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
springdoc:
swagger-ui:
enabled: true # 开启Swagger UI界面
display-request-duration: true # 展示请求所耗时间ms
operationsSorter: method # api排序方式(alpha:字母, method:http方法)
path: /swagger-ui # Swagger UI路径
# paths-to-match: /public/**,/admin/** # 配置需要生成接口文档的接口路径
packages-to-scan: com.wjh.web # 配置需要生成接口文档的接口路径
#knife4j相关配置 可以不用改
knife4j:
enable: true
setting:
language: zh_cn
swagger-model-name: 实体类
logging:
config: classpath:logback.xml
level:
com.wjh: debug
http:
maxTotal: 100 #最大连接数
defaultMaxPerRoute: 20 #并发数
connectTimeout: 1000 #创建连接的最长时间
connectionRequestTimeout: 500 #从连接池中获取到连接的最长时间
socketTimeout: 10000 #数据传输的最长时间
staleConnectionCheckEnabled: true #提交请求前测试连接是否可用
validateAfterInactivity: 3000000 #可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立
4. application-dev.yml
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/flink?serverTimezone=UTC
username: root
password: root
initial-size: 8
max-active: 16
min-idle: 8
max-wait: 60000
test-while-idle: true
test-on-borrow: false
test-on-return: false
redis:
host: 192.168.59.144
port: 6379
password: WTsGpUzM5mug5f
database: 2
timeout: 60 #连接超时时间(毫秒)
jedis:
pool:
max_total: 500 #控制一个pool可分配多少个jedis实例,用来替换max-active,如果是jedis 2.4以后用该属性
#max-active: 10 #连接池最大连接数(负值表示没有限制)
max-wait: 3000 #连接池最大阻塞等待时间(负值表示没有限制)
max-idle: 10 #连接池最大空闲连接数
min-idle: 1 #连接汉最小空闲连接数
max_wait_millis: 1000 #最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制
min_evictable_idle_time_millis: 300000 #连接的最小空闲时间 默认1800000毫秒(30分钟)
num_tests_per_eviction_run: 3 #每次释放连接的最大数目,默认3
time_between_eviction_runs_millis: 30000 #逐出扫描的时间间隔(毫秒) 如果为负数,则不运行逐出线程, 默认-1
test_on_borrow: true #是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个
test_while_idle: true #在空闲时检查有效性, 默认false
elasticsearch:
rest:
url: 127.0.0.1
port: 9200
uris: 127.0.0.1:9200
scheme: http
connection-timeout: 1000
read-timeout: 3000
username:
password:
data:
elasticsearch:
cluster-name: my-application
cluster-nodes: 127.0.0.1:9300
md5: # md5加密
key: 76e7ac9d7134a81381af18b626c23088 # md5秘钥
snow: # 雪花算法
work:
id: 20
data:
id: 20
5. ElasticsearchConfig.java
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.message.BasicHeader;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import lombok.extern.slf4j.Slf4j;
/**
* @author
* @date 2024/3/12
* @since JDK 17
*/
@Slf4j
@Configuration
public class ElasticsearchConfig {
@Value("${spring.elasticsearch.rest.url}")
private String url;
@Value("${spring.elasticsearch.rest.port}")
private int port;
@Value("${spring.elasticsearch.rest.username}")
private String userName;
@Value("${spring.elasticsearch.rest.password}")
private String password;
@Value("${spring.elasticsearch.rest.scheme}")
private String scheme;
@Bean
public ElasticsearchClient getClient() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
Header[] defaultHeaders = { new BasicHeader("charset", "utf-8"),
new BasicHeader("content-type", "application/json") };
RestClientBuilder clientBuilder = RestClient.builder(new HttpHost(url, port, scheme));
clientBuilder.setHttpClientConfigCallback(
httpClientBuilder -> httpClientBuilder.setDefaultHeaders(Arrays.asList(defaultHeaders))
.addInterceptorLast((HttpResponseInterceptor) (response, context) -> response
.addHeader("X-Elastic-Product", "Elasticsearch")));
RestClient restClient = clientBuilder.build();
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
return new ElasticsearchClient(transport);
}
}
6. ElasticsearchController.java
import com.wjh.request.FilePageRequest;
import io.swagger.v3.oas.annotations.Parameter;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.alibaba.fastjson2.JSON;
import com.wjh.base.ResponseApiData;
import com.wjh.entity.FileInfo;
import com.wjh.request.KeyPageRequest;
import com.wjh.service.IFileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
/**
* @author
* @date 2024/3/12
* @since JDK 17
*/
@Slf4j
@Tag(name = "Elasticsearch AIP接口", description = "Elasticsearch AIP接口")
@RestController
@RequestMapping("/api/es")
public class ElasticsearchController {
@Autowired
private IFileService fileService;
@Operation(summary = "保存文件信息", description = "保存文件信息")
@PostMapping("/save/file")
public ResponseApiData<?> saveFile(@RequestBody FileInfo fileInfo) {
log.info("保存文件信息-开始.请求参数:{}", JSON.toJSONString(fileInfo));
try {
fileService.save(fileInfo);
return ResponseApiData.success();
} catch (Exception e) {
log.error(String.format("保存文件信息-失败.请求参数:%s", JSON.toJSONString(fileInfo)), e);
return ResponseApiData.systemFail("保存文件信息失败");
}
}
@Operation(summary = "根据关键字分页查询", description = "根据关键字分页查询")
@PostMapping("/file/keyPage")
public ResponseApiData<Page<FileInfo>> keyPage(@RequestBody KeyPageRequest request) {
log.info("根据关键字分页查询-开始.请求参数:{}", JSON.toJSONString(request));
try {
return ResponseApiData.success(fileService.keyPage(request));
} catch (Exception e) {
log.error(String.format("根据关键字分页查询-失败.请求参数:%s", JSON.toJSONString(request)), e);
return ResponseApiData.systemFail("根据关键字分页查询失败");
}
}
@Operation(summary = "分页查询文件信息", description = "分页查询文件信息")
@PostMapping("/file/page")
public ResponseApiData<Page<FileInfo>> filePage(@RequestBody FilePageRequest request) {
log.info("分页查询文件信息-开始.请求参数:{}", JSON.toJSONString(request));
try {
return ResponseApiData.success(fileService.page(request));
} catch (Exception e) {
log.error(String.format("分页查询文件信息-失败.请求参数:%s", JSON.toJSONString(request)), e);
return ResponseApiData.systemFail("分页查询文件信息失败");
}
}
@Operation(summary = "查询文件详情", description = "查询文件详情",
parameters = {@Parameter(name = "id", description = "id")}
)
@GetMapping("/file/detail/{id}")
public ResponseApiData<FileInfo> fileDetail(@PathVariable String id) {
log.info("查询文件详情-开始.id:{}", id);
if (StringUtils.isBlank(id)) {
return ResponseApiData.parameterFail("id不能为空");
}
try {
return ResponseApiData.success(fileService.detail(id));
} catch (Exception e) {
log.error(String.format("查询文件详情-失败.id:%s", id), e);
return ResponseApiData.systemFail("查询文件详情失败");
}
}
}
7. IFileService.java
/**
* @author
* @date 2024/3/12
* @since JDK 17
*/
public interface IFileService {
void save(FileInfo fileInfo);
FileInfo detail(String id);
/**
* 根据关键字分页查询
*
* @date 2024-03-13
* @param request 请求参数
* @return Page
* @since JDK 17
* @author
*/
Page<FileInfo> keyPage(KeyPageRequest request);
/**
* 分页查询文件信息
*
* @date 2024-03-13
* @param request 查询条件
* @return Page
* @since JDK 17
* @author
*/
Page<FileInfo> page(FilePageRequest request);
}
8. FileServiceImpl.java
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Order;
import org.springframework.stereotype.Service;
import com.wjh.common.CommonMethods;
import com.wjh.common.Constants;
import com.wjh.entity.FileInfo;
import com.wjh.mapper.IFileRepository;
import com.wjh.request.FilePageRequest;
import com.wjh.request.KeyPageRequest;
import com.wjh.service.IFileService;
import com.wjh.utils.DateUtil;
import com.wjh.utils.JsonUtils;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders;
import co.elastic.clients.json.JsonData;
import lombok.extern.slf4j.Slf4j;
/**
* @author
* @date 2024/3/12
* @since JDK 17
*/
@Slf4j
@Service
public class FileServiceImpl implements IFileService {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private IFileRepository fileRepository;
@Override
public void save(FileInfo fileInfo) {
if (fileInfo.getId() == null || StringUtils.isBlank(fileInfo.getId())) {
fileInfo.setId(CommonMethods.getMeUUID());
}
if (fileInfo.getCreateTime() == null) {
fileInfo.setCreateTime(new Date());
}
if (fileInfo.getUpdateTime() == null) {
fileInfo.setUpdateTime(new Date());
}
fileRepository.save(fileInfo);
}
@Override
public FileInfo detail(String id) {
if (StringUtils.isBlank(id)) {
return null;
}
Optional<FileInfo> opt = fileRepository.findById(id.trim());
return opt.orElse(null);
}
/**
* 根据关键字分页查询
*
* @date 2024-03-13
* @param request 请求参数
* @return Page
* @since JDK 17
* @author
*/
@Override
public Page<FileInfo> keyPage(KeyPageRequest request) {
if (request.getPageNo() == null || request.getPageNo().intValue() <= 0) {
request.setPageNo(Constants.DEFAULT_PAGE_NUM);
}
if (request.getPageSize() == null || request.getPageSize() <= 0) {
request.setPageSize(Constants.DEFAULT_PAGE_SIZE);
}
int offset = (request.getPageNo() - 1) * request.getPageSize();
Sort sort = Sort.by(new Order(Sort.Direction.DESC, "create_time")/*,new Order(Sort.Direction.DESC, "_score")*/);
Pageable pageable = PageRequest.of(offset, request.getPageSize(), sort);
BoolQuery.Builder bqb = QueryBuilders.bool();
if (StringUtils.isNotBlank(request.getKeyword())) {
// 模糊查询
bqb.must(m -> m.match(ma -> ma.field("content").query(request.getKeyword().trim())));
}
NativeQueryBuilder nativeQueryBuilder = new NativeQueryBuilder();
nativeQueryBuilder.withQuery(bqb.build()._toQuery()).withPageable(pageable);
NativeQuery nativeQuery = nativeQueryBuilder.build();
SearchHits<FileInfo> searchHits = elasticsearchTemplate.search(nativeQuery, FileInfo.class);
long totalCount = searchHits.getTotalHits();
List<SearchHit<FileInfo>> searchHitList = searchHits.getSearchHits();
Page<FileInfo> page = new PageImpl<>(new ArrayList<>(), pageable, totalCount);
if (CollectionUtils.isNotEmpty(searchHitList)) {
List<FileInfo> fileList = new ArrayList<>(searchHitList.size());
for (SearchHit<FileInfo> searchHit : searchHitList) {
fileList.add(searchHit.getContent());
}
page = new PageImpl<>(fileList, pageable, totalCount);
}
return page;
}
/**
* 分页查询文件信息
*
* @param request 查询条件
* @return Page
* @date 2024-03-13
* @author
* @since JDK 17
*/
@Override
public Page<FileInfo> page(FilePageRequest request) {
// 去除前后空格
request = CommonMethods.beanStrim(request);
if (request.getPageNo() == null || request.getPageNo().intValue() <= 0) {
request.setPageNo(Constants.DEFAULT_PAGE_NUM);
}
if (request.getPageSize() == null || request.getPageSize() <= 0) {
request.setPageSize(Constants.DEFAULT_PAGE_SIZE);
}
// 查询起始日期(yyyy-MM-dd)
String beginDate = request.getBeginDate();
// 查询截止日期(yyyy-MM-dd)
String endDate = request.getEndDate();
if (StringUtils.isNotBlank(beginDate) && beginDate.length() == Constants.DATE_LENGTH) {
request.setBeginDate(beginDate + " 00:00:00");
}
if (StringUtils.isNotBlank(endDate) && endDate.length() == Constants.DATE_LENGTH) {
request.setEndDate(endDate + " 23:59:59");
}
final FilePageRequest filePageRequest = JsonUtils.parse(JsonUtils.toJSONBytes(request), FilePageRequest.class);
BoolQuery.Builder bqb = QueryBuilders.bool();
if (StringUtils.isNotBlank(filePageRequest.getFileName())) {
// 模糊查询
bqb.must(m -> m.match(ma -> ma.field("file_name").query(filePageRequest.getFileName())));
}
if (StringUtils.isNotBlank(filePageRequest.getFileType())) {
// 模糊查询
bqb.must(m -> m.match(ma -> ma.field("file_type").query(filePageRequest.getFileType())));
}
if (StringUtils.isNotBlank(filePageRequest.getBeginDate())) {
// RangeQuery rangeQuery = QueryBuilders.range().field("create_time").gte(JsonData.of(filePageRequest.getBeginDate())).build();
Query query =
Query.of(q -> q
.range(r -> {
r.field("create_time");
r.gte(JsonData.of(DateUtil.parseDate(filePageRequest.getBeginDate(), DateUtil.formatPattern)));
return r;
}
)
);
bqb.must(query);
}
if (StringUtils.isNotBlank(filePageRequest.getEndDate())) {
Query query =
Query.of(q -> q
.range(r -> {
r.field("create_time");
r.lte(JsonData.of(DateUtil.parseDate(filePageRequest.getEndDate(), DateUtil.formatPattern)));
return r;
}
)
);
bqb.must(query);
}
int offset = (filePageRequest.getPageNo() - 1) * filePageRequest.getPageSize();
Sort sort = Sort.by(new Order(Sort.Direction.DESC, "create_time")/*,new Order(Sort.Direction.DESC, "_score")*/);
Pageable pageable = PageRequest.of(offset, filePageRequest.getPageSize(), sort);
NativeQueryBuilder nativeQueryBuilder = new NativeQueryBuilder();
nativeQueryBuilder.withQuery(bqb.build()._toQuery()).withPageable(pageable);
NativeQuery nativeQuery = nativeQueryBuilder.build();
SearchHits<FileInfo> searchHits = elasticsearchTemplate.search(nativeQuery, FileInfo.class);
long totalCount = searchHits.getTotalHits();
List<SearchHit<FileInfo>> searchHitList = searchHits.getSearchHits();
Page<FileInfo> page = new PageImpl<>(new ArrayList<>(), pageable, totalCount);
if (CollectionUtils.isNotEmpty(searchHitList)) {
List<FileInfo> fileList = new ArrayList<>(searchHitList.size());
for (SearchHit<FileInfo> searchHit : searchHitList) {
fileList.add(searchHit.getContent());
}
page = new PageImpl<>(fileList, pageable, totalCount);
}
return page;
}
}
9. IFileRepository.java
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import com.wjh.entity.FileInfo;
/**
* @author
* @date 2024/3/12
* @since JDK 17
*/
//@Repository
public interface IFileRepository extends ElasticsearchRepository<FileInfo, String> {
}
10. FileInfo.java
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
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;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* Elasticsearch 实体类
*
* @author
* @date 2024/3/12
* @since JDK 17
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
@Document(indexName = "file_info", createIndex = false)
public class FileInfo implements Serializable {
@Serial
private static final long serialVersionUID = 4651439852938664760L;
/** 主键 */
@Field(name = "id", type = FieldType.Long)
@Id
private String id;
/** 文件名称 */
@Field(name = "file_name", type = FieldType.Text, analyzer = "jieba_index", searchAnalyzer = "jieba_index")
private String fileName;
/**
* 文件类型
*/
@Field(name = "file_type", type = FieldType.Keyword)
private String fileType;
/**
* 内容类型
*/
@Field(name = "content_type", type = FieldType.Text)
private String contentType;
/**
* 附件内容
*/
@Field(name = "content", type = FieldType.Text, analyzer = "jieba_index", searchAnalyzer = "jieba_index")
@TableField(exist = false)
private String content;
/**
* 文件地址
*/
@Field(name = "file_url", type = FieldType.Text)
private String fileUrl;
/**
* 创建时间
*/
@Field(name = "create_time", type = FieldType.Date)
private Date createTime;
/**
* 更新时间
*/
@Field(name = "update_time", type = FieldType.Date)
private Date updateTime;
}
11. JsonUtils.java
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
/**
* @author
* @date 2022/5/29
* @since JDK 17
*/
public final class JsonUtils {
private JsonUtils() {
}
/**
* 根据JSON字符串解析出java对象
* <p>
* 需要提供java对象类型
*
* @param text JSON字符串,不能为<code>NULL</code>
* @param clazz java对象类型
* @return java对象
*/
public static final <T> T parse(String text, Class<T> clazz) {
return JSON.parseObject(text, clazz);
}
/**
* 根据字节数组解析出java对象
* <p>
* 需要提供java对象类型
*
* @param input 字节数组
* @param clazz java对象类型
* @return java对象
*/
public static final <T> T parse(byte[] input, Class<T> clazz) {
return JSON.parseObject(input, clazz, new Feature[0]);
}
/**
* 根据java对象转换成字节数组
* <p>
* 按照默认方式转换,只输出属性和属性值信息,不加入任何其他类型信息
*
* @param object java对象
* @return 字节数组
*/
public static final byte[] toJSONBytes(Object object) {
return JSON.toJSONBytes(object, new SerializerFeature[0]);
}
/**
* 获取JSON串中指定的key对应的值
*
* @param json
* @param key
* @return String
* @author
* @date 2018年11月12日
* @since JDK 1.7
*/
public static String getJsonValue(String json, String key) {
if (StringUtils.isBlank(json) || StringUtils.isBlank(key)) {
return null;
}
JSONObject jsonObj = JSONObject.parseObject(json);
return jsonObj.getString(key);
}
/**
* 获取JSON串中指定的key对应的值
*
* @param json 数组
* @param key
* @return String
* @author
* @date 2018年12月12日
* @since JDK 1.7
*/
public static List<String> getJsonArrayValue(String json, String key) {
if (StringUtils.isBlank(json) || StringUtils.isBlank(key)) {
return null;
}
List<String> list = new ArrayList<>();
JSONArray jsonArray = JSON.parseArray(json);
if (jsonArray != null) {
for (int i = 0; i < jsonArray.size(); i++) {
JSONObject jsonObj = jsonArray.getJSONObject(i);
list.add(jsonObj.getString(key));
}
}
return list;
}
public static String toJsonStringFormat(Object obj) {
// 自定义时间格式
JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
return JSON.toJSONString(obj, //
// SerializerFeature.PrettyFormat, // 格式化结果
SerializerFeature.WriteMapNullValue, // 输出值为null的字段
SerializerFeature.WriteNullStringAsEmpty, // 字符类型字段如果为null,输出为”“,而非null
// SerializerFeature.WriteNullNumberAsZero, // 数值字段如果为null,输出为0,而非null
// SerializerFeature.DisableCircularReferenceDetect, // 消除对同一对象循环引用的问题
SerializerFeature.WriteNullListAsEmpty, // List字段如果为null,输出为[],而非null
SerializerFeature.WriteDateUseDateFormat, // 自定义时间格式
SerializerFeature.DisableCircularReferenceDetect // 消除循环引用
);
}
}
12. DateUtil.java
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
/**
* 日期工具类
* @author zsq
*/
public class DateUtil {
public static final String formatPattern = "yyyy-MM-dd HH:mm:ss";
public static final String formatPattern2 = "HH:mm:ss";
public static final String formatPattern3 = "yyyy-MM-dd";
public static final String formatPattern4 = "yyyy-MM-dd HH:mm";
public static final String formatPattern5 = "HH:mm";
/**
* 避免高并发下,多线程引发的时间错误,报错问题,SimpleDateFormat是线程不安全的
*/
public static ThreadLocal<DateFormat> DATE_FORMAT = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat(formatPattern);
}
};
/**
* 避免高并发下,多线程引发的时间错误,报错问题,SimpleDateFormat是线程不安全的
*/
public static ThreadLocal<DateFormat> DATE_FORMAT_3 = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat(formatPattern3);
}
};
/**
* 避免高并发下,多线程引发的时间错误,报错问题,SimpleDateFormat是线程不安全的
*/
public static ThreadLocal<DateFormat> DATE_FORMAT_4 = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat(formatPattern4);
}
};
/**
* 避免高并发下,多线程引发的时间错误,报错问题,SimpleDateFormat是线程不安全的
*/
public static ThreadLocal<DateFormat> DATE_FORMAT_5 = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat(formatPattern5);
}
};
/**
* 获取当前时间字符串
* @return
*/
public static String getNowTimeStr(){
Date nowTime = Calendar.getInstance().getTime();
String nowTimeStr = DATE_FORMAT.get().format(nowTime);
return nowTimeStr;
}
/**
* 格式化日期对象
* @param time
* @return
*/
public static String format(Date time){
return format(time, formatPattern);
}
/**
* 格式化日期对象
* @param time
* @param pattern
* @return
*/
public static String format(Date time, String pattern){
DateFormat dateFormat = new SimpleDateFormat(pattern);
String str = dateFormat.format(time);
return str;
}
/**
* 格式化日期对象
* @param time
* @return
*/
public static String format(Date time, DateFormat dateFormat){
String str = dateFormat.format(time);
return str;
}
/**
* 字符串转日期对象
* @param timeStr
* @param pattern
* @return
*/
public static Date parseDate(String timeStr, String pattern) {
try {
DateFormat dateFormat = new SimpleDateFormat(pattern);
Date parseDate = dateFormat.parse(timeStr);
return parseDate;
} catch (Exception e) {
return null;
}
}
/**
* 字符串转日期对象
* @param timeStr
* @param dateFormat
* @return
*/
public static Date parseDate(String timeStr, DateFormat dateFormat) throws ParseException {
Date parseDate = dateFormat.parse(timeStr);
return parseDate;
}
/**
* 字符串转日期对象
* @param timeStr
* @return
*/
public static Date parseDate(String timeStr) throws ParseException {
return parseDate(timeStr, formatPattern);
}
/**
* 两个日期对象相差秒
* @return
*/
public static long diffSecond(Date begin, Date end){
long diffMillisecond = end.getTime() - begin.getTime();
return diffMillisecond / 1000L;
}
/**
* 判断日期在两个日期之间
* @param begin 开始日期
* @param mid 判断的日期
* @param end 结束日期
* @return 是否存在俩日期之间
*/
public static boolean betweenDays(Date begin, Date mid, Date end){
if(mid.getTime() >= begin.getTime() && mid.getTime() < end.getTime()){
return true;
}
return false;
}
/**
* 获取当前日期之前或之后的指定天数的日期
* @param num 指定天数
* @return 指定天数之前或之后的日期
*/
public static Date getBeforeOrAfterDay(int num) {
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, num);
return c.getTime();
}
}
13. EsPageRequest.java
import java.io.Serial;
import java.io.Serializable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 分页查询 公共请求参数
*
* @author
* @date 2024/3/13
* @since JDK 17
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
public class EsPageRequest implements Serializable {
@Serial
private static final long serialVersionUID = 2403543093430201749L;
/** 第几页 */
@Schema(description = "第几页", example = "1")
private Integer pageNo;
/** 每页数量 */
@Schema(description = "每页数量", example = "10")
private Integer pageSize;
/** 查询起始日期(yyyy-MM-dd) */
@Schema(description = "查询起始日期(yyyy-MM-dd)", example = "2024-01-01")
private String beginDate;
/** 查询截止日期(yyyy-MM-dd) */
@Schema(description = "查询截止日期(yyyy-MM-dd)", example = "2024-12-31")
private String endDate;
}
14. KeyPageRequest.java
import java.io.Serial;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 根据关键字分页查询 请求参数
*
* @author
* @date 2024/3/13
* @since JDK 17
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
public class KeyPageRequest extends EsPageRequest {
@Serial
private static final long serialVersionUID = 6781615780605296835L;
/** 关键字 */
@Schema(description = "关键字")
private String keyword;
}
15. FilePageRequest.java
import java.io.Serial;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* 分页查询文件信息 请求参数
*
* @author
* @date 2024/3/13
* @since JDK 17
*/
@Data
@EqualsAndHashCode(callSuper = false)
@ToString(callSuper = true)
public class FilePageRequest extends EsPageRequest {
@Serial
private static final long serialVersionUID = 4370781146647964020L;
/** 文件名称 */
@Schema(description = "文件名称")
private String fileName;
/** 文件类型 */
@Schema(description = "文件类型")
private String fileType;
}