Java学者 发表于 2022-5-25 16:54

推荐一个 Spring Boot 3 + Vue 3 的实战型开源项目,配备保姆级项目开发教程

本帖最后由 Java学者 于 2023-1-11 20:15 编辑

## 项目简介

novel 是一套基于时下**最新** Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离**学习型**小说项目,配备[保姆级教程](https://docs.xxyopen.com/course/novel)手把手教你**从零开始**开发上线一套生产级别的 Java 系统,由小说门户系统、作家后台管理系统、平台后台管理系统、爬虫管理系统等多个子系统构成。包括小说推荐、作品检索、小说排行榜、小说阅读、小说评论、会员中心、作家专区、充值订阅、新闻发布等功能。

## 项目地址

- 后端项目(更新中):(https://github.com/201206030/novel) | [码云](https://gitee.com/novel_dev_team/novel)
- 前端项目(更新中):(https://github.com/201206030/novel-front-web) | [码云](https://gitee.com/novel_dev_team/novel-front-web)
- 线上应用版:(https://github.com/201206030/novel-plus) | [码云](https://gitee.com/novel_dev_team/novel-plus)
- 微服务版:(https://github.com/201206030/novel-cloud) | [码云](https://gitee.com/novel_dev_team/novel-cloud)

## 开发环境

- MySQL 8.0
- Redis 7.0
- Elasticsearch 8.2.0(可选)
- RabbitMQ 3.10.2(可选)
- XXL-JOB 2.3.1(可选)
- JDK 17
- Maven 3.8
- Node 16.14

**注:Elasticsearch、RabbitMQ 和 XXL-JOB 默认关闭,可通过 application.yml 配置文件中相应的 `enable` 配置属性开启。**

## 后端技术选型

| 技术                  |       版本       | 说明                  |
|---------------------|:--------------:|---------------------|
| Spring Boot         | 3.0.0 | 容器 + 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       | 分布式缓存支持             |
| Redisson            |      3.17.4       | 分布式锁实现            |
| MySQL               |      8.0       | 数据库服务               |
| ShardingSphere-JDBC |      5.1.1       | 数据库分库分表支持         |
| Elasticsearch       |   8.2.0      | 搜索引擎服务            |
| RabbitMQ            |   3.10.2   | 开源消息中间件             |
| XXL-JOB             |   2.3.1      | 分布式任务调度平台         |
| Sentinel            |   1.8.4      | 流量控制组件            |
| Springdoc-openapi   |   2.0.0      | Swagger 3 接口文档自动生成|
| Spring Boot Admin   |   3.0.0-M1      | 应用管理和监控             |
| Undertow            |2.2.17.Final| Java 开发的高性能 Web 服务器 |
| 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,面向设计师和开发者的组件库   |
## 示例代码

代码严格遵守阿里编码规约。

```java
/**
* 小说搜索
*/
@Override
public 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));

}
```

RoyPenn 发表于 2022-5-25 17:00

很棒,支持下

你好港屿 发表于 2022-5-25 17:45

还是很不错啊

Mr.wang 发表于 2022-5-25 18:26

牛牛牛,有空了学习学习

zhczlzhang 发表于 2022-5-25 19:13

做一个小说网站吗。

NCGZS 发表于 2022-5-26 23:46

大佬牛,有空学习下

hrjmo 发表于 2022-5-30 13:35

插眼,后面再看,谢谢大佬分享

daokunn 发表于 2022-6-1 16:55

这个网站界面看起来很清爽{:1_921:}

傲天越 发表于 2022-6-1 18:16

正在学习spring boot,多谢楼主分享!!!

angel_bai 发表于 2022-6-7 08:19

谢谢分享 学习下
页: [1] 2 3 4 5 6
查看完整版本: 推荐一个 Spring Boot 3 + Vue 3 的实战型开源项目,配备保姆级项目开发教程