novel 是一套基于时下最新 Java 技能栈 Spring Boot 3 + Vue 3 开拓的前后端分离学习型小说项目,配备保姆级项目开拓教程手把手教你从零开始开拓上线一个生产级别的 Java 系统。由小说门户系统、作家后台管理系统、平台后台管理系统等多个子系统构成。包括小说推举、作品检索、小说排行榜、小说阅读、小说评论、会员中央、作家专区、充值订阅、新闻发布等功能。
项目地址后端项目(更新中):GitHub | 码云后端微做事版本项目(待更新):GitHub | 码云前端项目(更新中):GitHub | 码云线上运用版:GitHub | 码云 |演示地址开拓环境MySQL 8.0Redis 7.0Elasticsearch 8.2.0(可选)RabbitMQ 3.10.2(可选)JDK 17Maven 3.8IntelliJ IDEA 2021.3(可选)Node 16.14后端技能选型技能
版本

解释
Spring Boot
3.0.0-SNAPSHOT
容器 + MVC 框架
Mybatis
3.5.9
ORM 框架
MyBatis-Plus
3.5.1
Mybatis 增强工具
JJWT
0.11.5
JWT 登录支持
Lombok
1.18.24
简化工具封装工具
Caffeine
3.1.0
本地缓存支持
Redis
7.0
分布式缓存支持
MySQL
8.0
数据库做事
Elasticsearch
8.2.0
搜索引擎做事
RabbitMQ
3.10.2
开源中间件
Undertow
2.2.17.Final
Java 开拓的高性能 Web 做事器
Docker
-
运用容器引擎
Jenkins
-
自动化支配工具
Sonarqube
-
代码质量掌握
注:更多热门新技能待集成。
前端技能选型技能
版本
解释
Vue.js
3.2.13
渐进式 JavaScript 框架
Vue Router
4.0.15
Vue.js 的官方路由
axios
0.27.2
基于 promise 的网络要求库
element-plus
2.2.0
基于 Vue 3,面向设计师和开拓者的组件库
示例代码代码严格遵守阿里编码规约。
/ 小说搜索 /@Overridepublic RestResp<PageRespDto<BookInfoRespDto>> searchBooks(BookSearchReqDto condition) { SearchResponse<EsBookDto> response = esClient.search(s -> { SearchRequest.Builder searchBuilder = s.index(EsConsts.BookIndex.INDEX_NAME); // 构建搜索条件 buildSearchCondition(condition, searchBuilder); // 排序 if (!StringUtils.isBlank(condition.getSort())) { searchBuilder.sort(o -> o.field(f -> f.field(condition.getSort()).order(SortOrder.Desc)) ); } // 分页 searchBuilder.from((condition.getPageNum() - 1) condition.getPageSize()) .size(condition.getPageSize()); return searchBuilder; }, EsBookDto.class ); TotalHits total = response.hits().total(); List<BookInfoRespDto> list = new ArrayList<>(); List<Hit<EsBookDto>> hits = response.hits().hits(); for (Hit<EsBookDto> hit : hits) { EsBookDto book = hit.source(); list.add(BookInfoRespDto.builder() .id(book.getId()) .bookName(book.getBookName()) .categoryId(book.getCategoryId()) .categoryName(book.getCategoryName()) .authorId(book.getAuthorId()) .authorName(book.getAuthorName()) .wordCount(book.getWordCount()) .lastChapterName(book.getLastChapterName()) .build()); } return RestResp.ok(PageRespDto.of(condition.getPageNum(), condition.getPageSize(), total.value(), list));}/ 构建搜索条件 /private void buildSearchCondition(BookSearchReqDto condition, SearchRequest.Builder searchBuilder) { BoolQuery boolQuery = BoolQuery.of(b -> { if (!StringUtils.isBlank(condition.getKeyword())) { // 关键词匹配 b.must((q -> q.multiMatch(t -> t .fields(EsConsts.BookIndex.FIELD_BOOK_NAME + "^2" , EsConsts.BookIndex.FIELD_AUTHOR_NAME + "^1.8" , EsConsts.BookIndex.FIELD_BOOK_DESC + "^0.1") .query(condition.getKeyword()) ) )); } // 精确查询 if (Objects.nonNull(condition.getWorkDirection())) { b.must(TermQuery.of(m -> m .field(EsConsts.BookIndex.FIELD_WORK_DIRECTION) .value(condition.getWorkDirection()) )._toQuery()); } if (Objects.nonNull(condition.getCategoryId())) { b.must(TermQuery.of(m -> m .field(EsConsts.BookIndex.FIELD_CATEGORY_ID) .value(condition.getCategoryId()) )._toQuery()); } // 范围查询 if (Objects.nonNull(condition.getWordCountMin())) { b.must(RangeQuery.of(m -> m .field(EsConsts.BookIndex.FIELD_WORD_COUNT) .gte(JsonData.of(condition.getWordCountMin())) )._toQuery()); } if (Objects.nonNull(condition.getWordCountMax())) { b.must(RangeQuery.of(m -> m .field(EsConsts.BookIndex.FIELD_WORD_COUNT) .lt(JsonData.of(condition.getWordCountMax())) )._toQuery()); } if (Objects.nonNull(condition.getUpdateTimeMin())) { b.must(RangeQuery.of(m -> m .field(EsConsts.BookIndex.FIELD_LAST_CHAPTER_UPDATE_TIME) .gte(JsonData.of(condition.getUpdateTimeMin().getTime())) )._toQuery()); } return b; }); searchBuilder.query(q -> q.bool(boolQuery));}
部分截图首页
排行榜
详情页阅读页