写到这里,系列里已经出现过一长串名字:Sa-Token、MyBatis-Plus、Jsoup、ddddocr、MinIO……每次提到都只是一两句话带过。这一篇把它们集中起来,挨个说清楚四件事:它是什么、GitHub 在哪、它在这个项目里干了什么、为什么适合这里。
先说明一下写法。「为什么」这一栏,我不想写成「因为它很强大」这种废话,所以每一项我只写在这个具体项目里 它赢在哪,有时候也会写它不太舒服的地方。开源项目没有完美的,你用之前最好知道它的脾气。
项目的整体技术栈,在第 0 篇有一张表。下面按「后端 → 小程序 → 管理后台」的顺序来。

后端

Spring Boot

是什么 :Spring 家族里「开箱即用」的那一层。自动配置、内嵌服务器、一堆 starter,让你不用从一堆 XML 或配置类开始搭项目。 GitHub :https://github.com/spring-projects/spring-boot
在项目里干什么 :整个后端的骨架,版本 3.2.5,JDK 17。有意思的是,它在这里跑的不是传统的 Servlet/Tomcat,而是 WebFlux + Netty (第 2 篇讲过为什么,以及两种模式并存带来的一堆坑)。
为什么是它 :Java 后端的默认选项,没什么悬念。要连数据库、Redis、对象存储,要跑定时任务、发邮件,Spring Boot 的生态里每一样都有现成的 starter,时间可以花在「怎么用对」上,而不是「选什么」上。

Reactor 与 Reactor Netty

是什么 :Spring WebFlux 底下的响应式编程库(Mono、Flux 就是它的类型),以及基于 Netty 的 HTTP 服务端 / 客户端实现。 GitHub : - https://github.com/reactor/reactor-core - https://github.com/reactor/reactor-netty
在项目里干什么 :一是整个 WebFlux 的底层;二是 WebClient——调微博开放平台全部走它。三条经验之谈:连接超时和响应超时一定要设(项目里统一是连接 5 秒 / 响应 15 秒);阻塞的东西一律扔进 boundedElastic;ThreadLocal 在这里不可靠(Sa-Token 那个事故就是这么来的)。
为什么是它 :迁到 WebFlux 之后它就是默认选项,说不上选择。不过要诚实地说一句:响应式的学习曲线是真的陡,调试起来也比同步代码费劲。如果你的项目并发不大,同步的 Spring MVC 完全够用,而且更省心。 这个项目里微博、教务、微信、OCR 这些外部调用特别多,大量时间在等 IO,响应式才有明显价值。

Sa-Token

是什么 :一个国产的轻量级 Java 权限认证框架,登录认证、权限认证、会话管理、踢人下线、单点登录这些都有,API 很短:StpUtil.login(id)、StpUtil.getLoginId()、@SaCheckLogin。 GitHub :https://github.com/dromara/sa-token (官网文档 https://sa-token.cc )
在项目里干什么 : - 小程序用户的登录态:登录身份就是微信 openid,StpUtil.login(openid); - 会话持久化到 Redis,重启不掉线; - 管理后台另起一个独立的登录体系 (StpLogic("admin")),和用户端互不干扰; - 用 @SaCheckLogin 注解保护接口。
为什么是它 :这个选型我之前专门写过一篇,从 Shiro 到 Sa-Token,里面讲了它比 Spring Security 好上手在哪。放到这个项目里,还有两个具体的理由:一是它有 reactor 版的 starter ,WebFlux 能直接用;二是「双体系」(用户端、管理端)开箱就支持。
踩过的坑也要说:在 WebFlux 下它基于 ThreadLocal 的上下文会在切线程时丢掉 ,要自己处理(第 3 篇整篇都在讲这个)。这不是 Sa-Token 的问题,是响应式本身的问题,但你用的时候得知道。

MyBatis-Plus

是什么 :MyBatis 的增强工具。单表增删改查不用写 SQL,实体加个注解就能用。 GitHub :https://github.com/baomidou/mybatis-plus
在项目里干什么 :项目里的阻塞数据通道 ——用户、敏感词、课表这些存量的表,大量还是走它。
为什么是它 :最实际的原因是存量代码 。项目最早是 Servlet + MyBatis 的,WebFlux 是后来逐步迁的,没必要一次性全推倒重来。MyBatis-Plus 对简单 CRUD 的省力程度很高,只有复杂查询才需要自己写 SQL。

Spring Data R2DBC 与 MariaDB R2DBC 驱动

是什么 :R2DBC 是「响应式的数据库访问规范」,可以理解成响应式世界的 JDBC。Spring Data R2DBC 在它上面做了 Repository 抽象,再配一个具体数据库的驱动。 GitHub : - https://github.com/spring-projects/spring-data-relational (Spring Data R2DBC 在这个仓库里) - https://github.com/mariadb-corporation/mariadb-connector-r2dbc
在项目里干什么 :响应式的读路径 。列表、课表、反馈这些读多的地方走它,仓储类大概有二十多个。
为什么是它 :WebFlux 里如果数据库访问还是阻塞的,响应式的好处就被浪费了一半。所以读路径迁成了 R2DBC。
但它不是银弹,用的时候踩到的几个:对带非空 @Id 的实体,save() 会走 UPDATE,行不存在就报错,所以「有则更新无则插入」要自己手写 upsert ;这个驱动对 null 参数编码会报错,绑定前要把 null 清洗掉;代码注释里还记着一条——Repository 的删除方法在这个工程里实测静默不生效 ,所以需要删除的地方,改用了显式 SQL。所以比较稳妥的分工是:读路径用 R2DBC,复杂的写路径老老实实留给 MyBatis。

MariaDB

是什么 :MySQL 的开源分支,兼容性很好。 GitHub :https://github.com/MariaDB/server
在项目里干什么 :主库,所有业务数据都在里面,统一 utf8mb4(不然 emoji 存不进去)。
为什么是它 :兼容 MySQL 的 SQL 和使用习惯,Java 这边用官方的 MariaDB 驱动就行,没有额外的学习成本。

Redis

是什么 :内存里的数据结构服务器,字符串、List、Hash、Set 都有,读写极快。 GitHub :https://github.com/redis/redis
在项目里干什么 ,这是整个项目里用法最多的一个组件: - Sa-Token 的会话存储; - 教务登录队列 (用 List 做 FIFO 队列)和防重复提交的活跃锁 (SETNX 加过期时间); - 评论缓存(空结果也缓存,但 TTL 更短); - 管理端登录失败计数(账号 5 次 / IP 20 次,15 分钟窗口); - 教务代理池。
为什么是它 :一台 Redis 同时解决会话、队列、锁、缓存、计数五件事,运维上就一个组件。要提醒的只有一点:一定要设超时 。Redis 一抖,没有超时的请求会全部挂住(第 2 篇有这个教训)。

MinIO

是什么 :兼容 S3 协议的开源对象存储,一条 Docker 命令就能跑起来。 GitHub :https://github.com/minio/minio
在项目里干什么 :存所有的图片——投稿配图、教务验证码图、课表分享封面、反馈附件。
为什么是它 :不用租云厂商的对象存储,自己一台机器就行;接口兼容 S3,将来想换成云上的,改配置就能换,不用动代码。图片的内网连接地址和对外访问地址要分开配(第 7 篇)。

OkHttp 与 Retrofit

是什么 :OkHttp 是 Java / Android 上最常见的 HTTP 客户端;Retrofit 在它上面做了「把接口写成 Java 接口」的声明式封装。 GitHub : - https://github.com/lysine-dev/okhttp (原 square/okhttp,GitHub 会自动跳转) - https://github.com/lysine-dev/retrofit (原 square/retrofit)
在项目里干什么 :教务系统登录 和微信接口。微博那条链路已经全部迁到了 WebClient(README 里叫「OkHttp 清零」),但教务这块还留着它。
为什么还留着 :教务登录有两个需求 WebClient 不太顺手:一是要靠 CookieJar 管理 JSESSIONID 会话(第 12 篇讲过,会话要从 CookieJar 里取,不能靠响应头);二是要按请求选择代理 。这两个用 OkHttp 的 CookieJar 和 ProxySelector 很自然。不是所有东西都值得迁。

Jsoup

是什么 :Java 的 HTML 解析库,支持类似 jQuery 的 CSS 选择器,容错很好,脏 HTML 也能解析。 GitHub :https://github.com/jhy/jsoup
在项目里干什么 :解析教务系统的课表页面。用 div[class^=kbcontent] 这种选择器取出每门课;登录页里有没有 showMsg 元素,也是靠它来判断登录成不成功。
为什么是它 :解析外部 HTML 这件事,Jsoup 几乎是 Java 里的默认答案。它宽容——教务页面不是标准整齐的 HTML,用严格的 XML 解析器根本没法用。

Hutool

是什么 :一个国产的 Java 工具类大全,把字符串、日期、加密、JSON、集合这些零碎的活包成了顺手的静态方法。 GitHub :https://github.com/chinabugotech/hutool (原 dromara/hutool,GitHub 会自动跳转)
在项目里干什么 :项目里随处可见的小事:BCrypt 校验管理员密码、SecureUtil.aes 加密教务密码、JSONUtil 解析微博的返回、RandomUtil 取随机延迟。
为什么是它 :省事。但也有一个提醒:Hutool 很全,容易让你什么都往它身上靠。像 AES 这种,密钥长度这类细节它不替你检查 (第 12 篇那个 17 字节密钥的故事)。工具库省的是敲代码的时间,不替你做安全决策。

imgscalr

是什么 :一个很简单的 Java 图片缩放库,等比缩放、抗锯齿,几行代码搞定。 GitHub :https://github.com/rkalla/imgscalr
在项目里干什么 :投稿图片超过 1920×1080 时等比缩放,再压成 JPG。
为什么是它 :只做这一件事,简单。它是一个相当老的库,属于「老但够用」——如果要做复杂的图像处理,该换别的。

ddddocr

是什么 :一个开源的通用验证码识别库,Python 写的,用深度学习模型,开箱即用,不需要自己训练。 GitHub :https://github.com/sml2h3/ddddocr
在项目里干什么 :识别教务系统登录时的验证码。我把它用 Docker 部署成一个独立的 HTTP 服务,后端通过 POST /classification 把图片(Base64)发过去,拿回识别文本。
为什么是它 :不用自己训练模型,这是最大的省事。以独立服务的方式部署,Java 后端和 Python 模型完全解耦,后端只需要会发一个 HTTP 请求。准确率不是 100%(所以才有多轮重试),这是前面几篇一直在强调的一点。

springdoc-openapi

是什么 :给 Spring 项目自动生成 OpenAPI 文档和 Swagger UI。 GitHub :https://github.com/springdoc/springdoc-openapi
在项目里干什么 :生成接口文档,在 Swagger 页面右上角填入登录返回的 token,就可以直接调试需要登录的接口。
为什么是它 :WebFlux 下用的是它的 webflux-ui 版本。接口一百多个,没有文档靠记忆是不现实的。

Lombok

是什么 :用注解(@Data、@Slf4j 之类)在编译期生成 getter/setter/日志对象这些样板代码。 GitHub :https://github.com/projectlombok/lombok
在项目里干什么 :实体类的 @Data,各个类里的 @Slf4j。
为什么是它 :省掉大量机械代码。唯一的代价是:它依赖编译期注解处理,换 IDE 或构建工具时,偶尔要确认一下插件有没有装好。

Gradle

是什么 :构建工具,用 Groovy 或 Kotlin 写构建脚本。 GitHub :https://github.com/gradle/gradle
在项目里干什么 :项目用的是 Kotlin DSL(build.gradle.kts),依赖管理和打包都在里面,并且把阿里云镜像放在了仓库列表最前面(直连 Maven 中央仓在国内不稳)。

小程序

Taro

是什么 :一个「一套代码,多端运行」的框架。你用 React 或 Vue 写,它帮你编译成微信小程序、支付宝小程序、H5 等等。 GitHub :https://github.com/NervJS/taro
在项目里干什么 :用 Vue 3 写微信小程序,版本 3.6.25。
为什么是它 :原生写法(WXML / WXSS)写大项目比较吃力,TypeScript 和工程化也要自己折腾。Taro 让你能用 Vue 3 的 <script setup> 加 TypeScript 来写,开发体验和写网页接近。一个提醒:@tarojs/* 这一堆包的版本必须完全一致,混着用是编译报错的常见来源。

Vue 3

是什么 :渐进式前端框架。 GitHub :https://github.com/vuejs/core
在项目里干什么 :小程序和管理后台都用它,<script setup> 的写法。

NutUI

是什么 :京东开源的 Vue 组件库,除了 H5 版,还有配合 Taro 的版本(@nutui/nutui-taro)。 GitHub :https://github.com/jd-opensource/nutui (原 jdf2e/nutui,GitHub 会自动跳转)
在项目里干什么 :小程序里的按钮、弹窗、表单、通知这些 UI 组件,版本 4.3。
为什么是它 :它和 Taro 配套,不用自己适配小程序环境。

Pinia

是什么 :Vue 官方推荐的状态管理库,是 Vuex 的接班人,写法简单很多。 GitHub :https://github.com/vuejs/pinia
在项目里干什么 :只管一件事:登录态 (token、是否已微信登录、是否已绑定教务)。小程序里需要全局共享的状态不多,所以 store 很小。

管理后台

后台的前端是一个单独的 Vue 3 单页应用,产物打进后端的 jar(第 15 篇)。

Vite

是什么 :新一代前端构建工具,开发时启动极快,构建基于 Rollup。 GitHub :https://github.com/vitejs/vite
在项目里干什么 :构建后台前端,产物直接输出到后端的静态资源目录;开发时把 /admin 代理到本地后端。

Element Plus

是什么 :Vue 3 的桌面端组件库,表格、表单、弹窗、分页,后台需要的它基本都有。 GitHub :https://github.com/element-plus/element-plus
在项目里干什么 :后台所有页面的 UI。
为什么是它 :后台的需求都是成熟需求,没必要自己造。

Vue Router 与 axios

GitHub : - Vue Router:https://github.com/vuejs/router - axios:https://github.com/axios/axios
在项目里干什么 :Vue Router 管后台十几个页面的路由,路由守卫里没登录就跳登录页;axios 封装了请求,拦截器统一加上 X-Admin-Token 请求头,遇到 401 就清掉登录态、跳回登录页。

链接汇总

用途项目GitHub
后端框架Spring Boothttps://github.com/spring-projects/spring-boot
响应式Reactor Corehttps://github.com/reactor/reactor-core
响应式 HTTPReactor Nettyhttps://github.com/reactor/reactor-netty
鉴权Sa-Tokenhttps://github.com/dromara/sa-token
ORMMyBatis-Plushttps://github.com/baomidou/mybatis-plus
响应式数据访问Spring Data Relationalhttps://github.com/spring-projects/spring-data-relational
响应式驱动MariaDB R2DBChttps://github.com/mariadb-corporation/mariadb-connector-r2dbc
数据库MariaDBhttps://github.com/MariaDB/server
缓存/队列Redishttps://github.com/redis/redis
对象存储MinIOhttps://github.com/minio/minio
HTTP 客户端OkHttphttps://github.com/lysine-dev/okhttp
声明式 HTTPRetrofithttps://github.com/lysine-dev/retrofit
HTML 解析Jsouphttps://github.com/jhy/jsoup
工具库Hutoolhttps://github.com/chinabugotech/hutool
图片缩放imgscalrhttps://github.com/rkalla/imgscalr
验证码识别ddddocrhttps://github.com/sml2h3/ddddocr
接口文档springdoc-openapihttps://github.com/springdoc/springdoc-openapi
样板代码Lombokhttps://github.com/projectlombok/lombok
构建Gradlehttps://github.com/gradle/gradle
小程序框架Tarohttps://github.com/NervJS/taro
前端框架Vue 3https://github.com/vuejs/core
组件库(小程序)NutUIhttps://github.com/jd-opensource/nutui
状态管理Piniahttps://github.com/vuejs/pinia
构建(后台)Vitehttps://github.com/vitejs/vite
组件库(后台)Element Plushttps://github.com/element-plus/element-plus
路由Vue Routerhttps://github.com/vuejs/router
请求axioshttps://github.com/axios/axios

最后

把这份清单整理出来之后会发现:这个项目没有一个「独门武器」 。每一个组件都是很常见的开源项目,真正花时间的地方,是它们之间怎么配合、坏了怎么办。
所以如果你正要做类似的项目,别太纠结「选哪个」。常见的、文档全的、中文社区活跃的,基本都行。把力气留给第 5、10、13 篇那些问题——失败怎么分类、限流怎么退避、重试怎么判定 ——那才是真正拉开差距的地方。

最后修改:2026 年 11 月 12 日
如果觉得我的文章对你有用,请随意赞赏