手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(一) – 介绍

虚幻大学 xuhss 183℃ 0评论

? 优质资源分享 ?

学习路线指引(点击解锁) 知识定位 人群定位
? Python实战微信订餐小程序 ? 进阶级 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。
?Python量化交易实战? 入门级 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统

项目简介

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

项目地址

开发环境

  • MySQL 8.0
  • Redis 7.0
  • Elasticsearch 8.2.0(可选)
  • RabbitMQ 3.10.2(可选)
  • JDK 17
  • Maven 3.8
  • IntelliJ 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,面向设计师和开发者的组件库

示例代码

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


|  | /** |
|  |  * 小说搜索 |
|  |  */ |
|  | @Override |
|  | public RestResp> searchBooks(BookSearchReqDto condition) { |
|  |  |
|  |  SearchResponse 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 list = new ArrayList<>(); |
|  |  List> hits = response.hits().hits(); |
|  | for (Hit 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)); |
|  |  |
|  | } |

转载请注明:xuhss » 手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(一) – 介绍

喜欢 (0)

您必须 登录 才能发表评论!