文章目录
🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)
轻松高效的现代化开发体验
Sun Frame 是我个人开源的一款基于 SpringBoot 的轻量级框架,专为中小型企业设计。它提供了一种快速、简单且易于扩展的开发方式。
我们的开发文档记录了整个项目从0到1的任何细节,实属不易,请给我们一个Star!🌟
您的支持是我们持续改进的动力。
您的支持是我们持续改进的动力。
🌟 亮点功能
- 组件化开发:灵活选择,简化流程。
- 高性能:通过异步日志和 Redis 缓存提升性能。
- 易扩展:支持多种数据库和消息队列。
📦 spring cloud模块概览
- Nacos 服务:高效的服务注册与发现。
- Feign 远程调用:简化服务间通信。
- 强大网关:路由与限流。
常用工具
- 日志管理:异步处理与链路追踪。
- Redis 集成:支持分布式锁与缓存。
- Swagger 文档:便捷的 API 入口。
- 测试支持:SpringBoot-Test 集成。
- EasyCode:自定义EasyCode模板引擎,一键生成CRUD。
🔗 更多信息
- 开源地址:Gitee Sun Frame
- 详细文档:语雀文档
1.sun-club-infra 模块
SubjectEsServiceImpl.java
1.querySubjectList方法:根据查询请求进行查询
@Override
public PageResult<SubjectInfoEs> querySubjectList(SubjectInfoEs req) {
// 构建一个返回的分页对象
PageResult<SubjectInfoEs> pageResult = new PageResult<>();
// 根据信息构建一个查询请求对象
EsSearchRequest esSearchRequest = createSearchListQuery(req);
// 获得分页查询结果
SearchResponse searchResponse = EsRestClient.searchWithTermQuery(getEsIndexInfo(), esSearchRequest);
// 构建一个要返回的数据对象
List<SubjectInfoEs> subjectInfoEsList = new LinkedList<>();
// 得到命中的数据
SearchHits searchHits = searchResponse.getHits();
if (searchHits == null || searchHits.getHits() == null) {
pageResult.setPageNo(req.getPageNo());
pageResult.setPageSize(req.getPageSize());
pageResult.setRecords(subjectInfoEsList);
pageResult.setTotal(0);
return pageResult;
}
// 如果有命中的
SearchHit[] hits = searchHits.getHits();
for (SearchHit hit : hits) {
// 将每个hit都转换为SubjectInfoEs,然后将其放到要返回的数据对象中
SubjectInfoEs subjectInfoEs = convertHit2SubjectInfoEs(hit);
subjectInfoEsList.add(subjectInfoEs);
}
// 构建分页对象
pageResult.setPageNo(req.getPageNo());
pageResult.setPageSize(req.getPageSize());
pageResult.setRecords(subjectInfoEsList);
pageResult.setTotal(Long.valueOf(searchHits.getTotalHits().value).intValue());
return pageResult;
}
2.convertHit2SubjectInfoEs方法:将每一个hit转换为SubjectInfoEs
/**
* 将每一个hit转换为SubjectInfoEs
* @param hit
* @return
*/
private SubjectInfoEs convertHit2SubjectInfoEs(SearchHit hit) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
if (CollectionUtils.isEmpty(sourceAsMap)) {
return null;
}
SubjectInfoEs result = new SubjectInfoEs();
// 封装基本数据
result.setSubjectId(MapUtils.getLong(sourceAsMap, EsSubjectFields.SUBJECT_ID));
result.setSubjectName(MapUtils.getString(sourceAsMap, EsSubjectFields.SUBJECT_NAME));
result.setSubjectAnswer(MapUtils.getString(sourceAsMap, EsSubjectFields.SUBJECT_ANSWER));
result.setDocId(MapUtils.getLong(sourceAsMap, EsSubjectFields.DOC_ID));
result.setSubjectType(MapUtils.getInteger(sourceAsMap, EsSubjectFields.SUBJECT_TYPE));
result.setScore(new BigDecimal(String.valueOf(hit.getScore())).multiply(new BigDecimal("100.00")
.setScale(2, RoundingMode.HALF_UP)));
//处理name的高亮
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
HighlightField subjectNameField = highlightFields.get(EsSubjectFields.SUBJECT_NAME);
if(Objects.nonNull(subjectNameField)){
Text[] fragments = subjectNameField.getFragments();
StringBuilder subjectNameBuilder = new StringBuilder();
for (Text fragment : fragments) {
subjectNameBuilder.append(fragment);
}
result.setSubjectName(subjectNameBuilder.toString());
}
//处理答案高亮
HighlightField subjectAnswerField = highlightFields.get(EsSubjectFields.SUBJECT_ANSWER);
if(Objects.nonNull(subjectAnswerField)){
Text[] fragments = subjectAnswerField.getFragments();
StringBuilder subjectAnswerBuilder = new StringBuilder();
for (Text fragment : fragments) {
subjectAnswerBuilder.append(fragment);
}
result.setSubjectAnswer(subjectAnswerBuilder.toString());
}
return result;
}
3.根据信息构建一个查询请求对象
/**
* 根据信息构建一个查询请求对象
* @param req
* @return
*/
private EsSearchRequest createSearchListQuery(SubjectInfoEs req) {
EsSearchRequest esSearchRequest = new EsSearchRequest();
// bq用来组合查询条件
BoolQueryBuilder bq = new BoolQueryBuilder();
// 查询条件1是根据题目名称查询
MatchQueryBuilder subjectNameQueryBuilder =
QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_NAME, req.getKeyWord());
// 查询条件2是根据题目的答案查询
MatchQueryBuilder subjectAnswerQueryBuilder =
QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_ANSWER, req.getKeyWord());
// 使用bq关联两个查询条件,should就相当于或者,就是两个都查
bq.should(subjectNameQueryBuilder);
// 让题目名的权重高2
subjectNameQueryBuilder.boost(2);
bq.should(subjectAnswerQueryBuilder);
// 查询条件3是只查询简答题
MatchQueryBuilder subjectTypeQueryBuilder =
QueryBuilders.matchQuery(EsSubjectFields.SUBJECT_TYPE, SubjectInfoTypeEnum.BRIEF.getCode());
// 必须是简答题
bq.must(subjectTypeQueryBuilder);
// 至少命中一个should
bq.minimumShouldMatch(1);
// 增加高亮
HighlightBuilder highlightBuilder = new HighlightBuilder().field("*").requireFieldMatch(false);
highlightBuilder.preTags("<span style = \"color:red\">");
highlightBuilder.postTags("</span>");
// 组装请求
// bq
esSearchRequest.setBq(bq);
// 高亮
esSearchRequest.setHighlightBuilder(highlightBuilder);
// 匹配字段(一般是全部)
esSearchRequest.setFields(EsSubjectFields.FIELD_QUERY);
// ==========返回分页查询的结果==========
// 当前页是从第几条记录开始,下标从1开始
esSearchRequest.setFrom((req.getPageNo() - 1) * req.getPageSize());
// 页面大小
esSearchRequest.setSize(req.getPageSize());
// ==========返回分页查询的结果==========
// 不需要快照缓存
esSearchRequest.setNeedScroll(false);
return esSearchRequest;
}
2.简单测试
1.TestFeignController.java
@RequestMapping("/querySubjectByKeyword")
public void querySubjectByKeyword() {
SubjectInfoEs subjectInfoEs = new SubjectInfoEs();
subjectInfoEs.setKeyWord("简答题目");
PageResult<SubjectInfoEs> subjectInfoEsPageResult = subjectEsService.querySubjectList(subjectInfoEs);
// 打印
log.info("querySubjectByKeyword:" + JSON.toJSONString(subjectInfoEsPageResult));
}
}
2.新增几条记录
2.查询
3.结果高亮显示
3.加上控制层的实现
1.DTO和BO都加上keyWord属性
2.SubjectController.java
/**
* 全文检索
* @param subjectInfoDTO
* @return
*/
@PostMapping("/getSubjectPageBySearch")
public Result<SubjectInfoEs> getSubjectPageBySearch(@RequestBody SubjectInfoDTO subjectInfoDTO) {
try {
// 打印日志
if (log.isInfoEnabled()) {
log.info("SubjectController getSubjectPageBySearch SubjectInfoDTO, subjectInfoDTO:{}", JSON.toJSONString(subjectInfoDTO));
}
// 参数校验
Preconditions.checkArgument(StringUtils.isNotBlank(subjectInfoDTO.getKeyWord()), "关键字不能为空");
// DTO转BO
SubjectInfoBO subjectInfoBO = SubjectInfoDTOConverter.INSTANCE.convertDTO2BO(subjectInfoDTO);
// 设置分页参数
subjectInfoBO.setPageNo(subjectInfoDTO.getPageNo());
subjectInfoBO.setPageSize(subjectInfoDTO.getPageSize());
// 全文检索
PageResult<SubjectInfoEs> boPageResult = subjectInfoDomainService.getSubjectPageBySearch(subjectInfoBO);
return Result.ok(boPageResult);
} catch (Exception e) {
log.error("SubjectController getSubjectPageBySearch error, subjectInfoDTO:{}", e.getMessage(), e);
return Result.fail("全文检索失败");
}
}
3.sun-club-domain
1.SubjectInfoDomainService.java
/**
* 全文检索
* @param subjectInfoBO
* @return
*/
PageResult<SubjectInfoEs> getSubjectPageBySearch(SubjectInfoBO subjectInfoBO);
2.SubjectInfoDomainServiceImpl.java
@Override
public PageResult<SubjectInfoEs> getSubjectPageBySearch(SubjectInfoBO subjectInfoBO) {
// 将bo转换为entity
SubjectInfoEs subjectInfoEs = new SubjectInfoEs();
subjectInfoEs.setKeyWord(subjectInfoBO.getKeyWord());
subjectInfoEs.setPageNo(subjectInfoBO.getPageNo());
subjectInfoEs.setPageSize(subjectInfoBO.getPageSize());
// 全文检索
PageResult<SubjectInfoEs> subjectInfoEsPageResult = subjectEsService.querySubjectList(subjectInfoEs);
return subjectInfoEsPageResult;
}