diff --git a/Readme.md b/Readme.md
index 0fe2ca28..4f5c9504 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,90 +1,145 @@
[](https://github.com/houko/SpringBootUnity/actions/workflows/build.yml)
-[](#backers) [](#sponsors) [](https://github.com/houko/SpringBootUnity/issues)
-[](https://raw.githubusercontent.com/houko/SpringBootUnity/main/LICENSE)
-[]()
+[](https://github.com/houko/SpringBootUnity/actions/workflows/codeql-analysis.yml)
+[](LICENSE)
+[](https://spring.io/projects/spring-boot)
+[](https://adoptium.net/)
+[](https://github.com/houko/SpringBootUnity/issues)
+[](#支持者) [](#赞助商)
+
+# SpringBootUnity
-### 项目简介

-### 环境
-- `maven` latest
-- `jdk21`
-- `spring boot 4.x release`
-- 个人推荐`idea`来代替eclipse
-- git: 版本管理
-- nginx: 反向代理服务器
+## 项目简介
+需求是多变的。本项目以 Spring Boot 为基础,针对不同需求把不同的技术和 Spring Boot 搭配起来,每一种搭配单独做成一个模块,因此它是一个偏使用示例的集合而非一个完整产品。
-### 注意事项
-- 本项目代码托管在[github](https://github.com/houko/SpringBootUnity)和[码云](http://git.oschina.net/hupeng_admin/SpringBootUnity)两个地方,最新代码会先推送在github上,码云上会在github上更新完之后进行同步。
-- 本项目多数数据库都用到了`hibernate`,如果没有提供`sql`文件。则启动时会根据代码映射自动生成数据库表,请在启动前修改`application.properties`中的数据库连接信息
+每个模块都能独立打包、独立启动,互不影响,可以只挑自己关心的那一个跑起来看。如果你在使用 Spring Boot 的过程中有什么好用的技术,欢迎提 PR。
+## 模块一览
-### 启动方式
+一共 16 个模块。`core` 是被其他模块共同依赖的基础包,其余每个模块各自演示一项技术。
-- 本地运行
-本repo是一个多模块组成,每一个模块都可以单独打包运行。如果想运行哪个模块可以找到对应的Main文件右键运行。
-
+| 模块 | 演示内容 | 启动类 | 需要的外部服务 |
+| --- | --- | --- | --- |
+| `core` | 公共基础包:工具类、基类、常量、异常、过滤器。被所有模块依赖,**不可独立运行** | — | — |
+| `website` | 个人站点:JPA + FreeMarker 页面 + OpenAPI 接口,模块中最完整的一个 | `XiaomoMain` | MySQL、Redis |
+| `javase` | Java SE 题库接口,JPA + OpenAPI 的典型增删改查 | `QuestionMain` | MySQL |
+| `order` | 订单接口,含 zxing 二维码生成 | `OrderMain` | — |
+| `mongodb` | MongoDB 文档数据库读写 | `MongodbMain` | MongoDB |
+| `mybatis` | MyBatis 替代 JPA 作为持久层 | `MybatisMain` | MySQL |
+| `multipleSource` | 多数据源配置与切换 | `MultipleSourceMain` | MySQL ×2 |
+| `redis` | Redis 缓存读写与定时刷新 | `RedisMain` | Redis |
+| `rabbitmq` | RabbitMQ 消息收发 | `RabbitMqMain` | RabbitMQ |
+| `security` | Spring Security 表单登录与鉴权 | `SecurityMain` | — |
+| `socket` | WebSocket 在线聊天,端口 **8081** | `ChatMain` | — |
+| `scheduled` | `@Scheduled` 定时任务 | `ScheduledMain` | — |
+| `async` | `@Async` 异步任务 | `AsyncMain` | — |
+| `crawler` | jsoup 网络爬虫(阴阳师式神数据),抓取后落库 | `CrawlerMain` | MySQL |
+| `freemarker` | FreeMarker 模板引擎 | `FreemarkerMain` | — |
+| `thymeleaf` | Thymeleaf 模板引擎 | `ThymeleafMain` | — |
+
+除 `socket` 使用 8081 外,其余模块都监听 **8080**,所以一次只启动一个模块。
+
+## 技术栈
+
+| 组件 | 版本 |
+| --- | --- |
+| Spring Boot | 4.1.1 |
+| JDK | 21(编译目标;CI 同时在 21 和 25 上构建) |
+| Maven | 3.9+ |
+| Hibernate / Spring Data JPA | 7.x |
+| Jackson | 3.x |
+| API 文档 | springdoc-openapi 3.x(OpenAPI 3.1) |
+| 数据库驱动 | MySQL Connector/J |
+| 其他 | MyBatis、Lettuce(Redis)、jsoup、Apache POI、fastjson2、zxing |
+Spring、Jackson、Hibernate、JUnit 等版本统一由 `spring-boot-dependencies` BOM 管理,不在本项目中单独指定。
-- 在linux服务器运行
- `spring boot`内置了tomcat做为web容器,默认打成jar包直接放在服务器上执行就可以了
-> `java -Xms64m -Xmx2048m -jar project.jar 5 >> ./project.log &`
+## 环境要求
+- JDK 21 或更高(Spring Boot 4 的最低要求是 17)
+- Maven 3.9 或更高
+- 按需准备对应模块的外部服务(见上表),只跑不需要外部服务的模块则无需任何准备
+## 快速开始
-### 打包
-- 如果需要定制化打成war包,那么也很简单。在`maven`中做下设置就ok了,然后把war包扔到tomcat下面就可以运行了
+构建全部模块:
+```bash
+mvn clean install
```
- 4.0.0
- api
- war
+
+启动某一个模块,例如不依赖任何外部服务的 `order`:
+
+```bash
+java -jar order/target/order-2020.1.jar
```
+也可以用 Maven 直接跑:
+
+```bash
+mvn spring-boot:run -pl order
+```
+
+在 IDE 中则找到对应模块的 `*Main` 类直接运行即可。
+
+
+
+部署到服务器时,Spring Boot 内置了 Tomcat,把打好的 jar 传上去执行就可以:
+
+```bash
+java -Xms64m -Xmx2048m -jar order-2020.1.jar >> ./order.log 2>&1 &
+```
+
+## API 文档
+
+带有 OpenAPI 注解的模块(`website`、`javase`、`order`、`mongodb`)启动后可访问:
-### 更新日志
-- 2017-09-02 api模块: 添加swagger-bootstrap-ui,和原有ui并行存在。
-http://localhost:8080 默认UI
-http://localhost:808/doc.html bootstrap-ui
-
-- 2017-09-02 spring boot版本从1.4.3更新到1.5.8
-- 2017-09-02 修复不配置数据库信息无法启动的bug
-- 2017-09-02 版本号更新到2017.1
-- 2017-09-02 api模块(swagger)添加开源库swagger-bootstrap-ui,和swagger默认UI同时存在。
-- 2017-09-02 web模块添加数据库sql文件,导入后一键启动可直接访问到web界面。
-- 2017-09-06 mybatis模块:添加USER.sql,启动后访问:http://localhost:8080 即可看到接口数据
-- 2017-09-06 所有模块: 添加 characterEncoding=utf8&useSSL=true 解决高版本mysql的sll警告
-- 2017-09-06 添加代码贡献者列表和支持者,赞助商链接。
-- 2017-09-08 crawler模块(网络爬虫):修复本地文件目录不存在会报错的bug。处理方式为:不存在则自动创建
-- 2017-11-02 开源协议从apache更换到MIT
-- 2017-11-02 添加本地运行方式的说明
-- 2017-11-02 版本更新到2020.1
-- 2017-11-02 spring boot版本更新到1.5.8
-- 2017-11-03 添加kotlin环境配置
-- 2017-11-03 按照阿里巴巴编程规范插件P3C优化代码
-- 2017-11-03 合并`api`和`website`模块,访问`localhost:8080`会显示网站主页,访问`localhost:8080/api`会显示api管理界面
-- 2018-04-09 将整个项目升级到spring boot2.0 release版本,api有较大变动
-- 2019-08-06 travis-ci指定jdk版本
-- 2020-10-09 升级版本到2020.2
-- 2020-10-09 升级jdk版本到11
-- 2020-10-09 升级mysql connector到8
-- 2020-10-09 升级spring boot到2.3.0
-- 2020-10-09 修复了升级后API的破坏性变动,修复了一些了编辑器警告
-- 2026-09-09 升级spring boot到4.1.1,jdk升级到21,全部依赖更新到最新版本
-- 2026-09-09 `javax.*` 迁移到 `jakarta.*`(persistence/servlet/mail/websocket)
-- 2026-09-09 api文档从已停止维护的springfox迁移到springdoc-openapi,swagger注解升级到OpenAPI 3
-- 2026-09-09 security模块改用SecurityFilterChain组件式配置,替换已移除的WebSecurityConfigurerAdapter
-- 2026-09-09 fastjson迁移到fastjson2,jackson升级到3.x,poi升级到5.x,dom4j迁移到org.dom4j
+- Swagger UI:
+- OpenAPI 描述文档:
+
+## 配置说明
+每个模块的配置在各自的 `src/main/resources/config/application.properties`,日志配置在同目录的 `logback-dev.xml`。
+
+需要注意:
+
+- 涉及数据库的模块请先修改 `spring.datasource.*` 中的连接信息。多数模块使用 Hibernate 的 `ddl-auto=update`,在没有提供 sql 文件时会依据实体类映射自动建表。
+- 仓库里的账号密码全部是占位符,**不要把真实凭据提交进版本库**。`core/src/main/resources/config/oauth.properties` 中的第三方登录密钥同理,请填入自己申请的值,或改为从环境变量注入。
+
+## 打包成 war
+
+如果需要部署到外部 Tomcat,在对应模块的 `pom.xml` 中改打包方式即可:
+
+```xml
+war
+```
+
+## 更新日志
+
+完整记录见 [changeLog.md](changeLog.md),以下为主要节点:
+
+- **2026-09-09** 升级到 Spring Boot 4.1.1、JDK 21,全部依赖更新到最新版本;`javax.*` 迁移到 `jakarta.*`;API 文档从已停止维护的 springfox 迁移到 springdoc-openapi;security 模块改用 `SecurityFilterChain` 组件式配置;fastjson 迁移到 fastjson2,Jackson 升级到 3.x,POI 升级到 5.x;新增 GitHub Actions 构建 CI
+- **2020-10-09** 升级到 Spring Boot 2.3.0、JDK 11,MySQL Connector 升级到 8
+- **2018-04-09** 升级到 Spring Boot 2.0 release,API 有较大变动
+- **2017-11-03** 合并 `api` 和 `website` 模块;按阿里巴巴编程规范 P3C 优化代码
+- **2017-11-02** 开源协议从 Apache 更换为 MIT
+- **2017-09-08** crawler 模块修复本地目录不存在时报错的问题
+
+## 项目状态
+
+本项目定位是示例集合,模块按需增删。欢迎通过 [issue](https://github.com/houko/SpringBootUnity/issues) 反馈问题或提出想看到的技术搭配。
+
+本项目同时托管在 [GitHub](https://github.com/houko/SpringBootUnity) 和 [Gitee](https://gitee.com/hupeng_admin/SpringBootUnity),以 GitHub 为准。
## 贡献者
感谢所有为本项目做出贡献的开发者们.
-
+
## 支持者
@@ -92,10 +147,9 @@ http://localhost:808/doc.html bootstrap-ui
-
## 赞助商
-[[成为赞助商](https://opencollective.com/SpringBootUnity#sponsor)]支持本项目并成为赞助商. 您的LOGO和网站链接将会被展示在这里.
+[[成为赞助商](https://opencollective.com/SpringBootUnity#sponsor)]支持本项目并成为赞助商. 您的 LOGO 和网站链接将会被展示在这里.
@@ -108,47 +162,22 @@ http://localhost:808/doc.html bootstrap-ui
-### 项目说明
-需求是多变的,本项目是以spring boot为基础,在使用spring boot的过程中对应不同的需求选用不同的技术和spring boot进行搭配,因此本项目是个偏于使用示例的定位。同时如果您在使用spring boot的过程中有什么好用的技术期待您对本项目的PR。
-
-### 关于我
- @[小莫](https://xiaomo.info):本人是一个热爱开源精神、追求新潮的开发者,技术过得去,还算勤勉!习惯以github的issue驱动方式来组织我的项目,也希望感兴趣的朋友和我联系,一起进步,共同开发感兴趣的开源项目。目前任rpg服务端主程,熟悉游戏开发和web开发。同时也是个喜欢二次元的死宅,爱动漫,略懂日语。
-
-### 在线小工具
-
-- [在线Cron表达式生成器](http://cron.qqe2.com/ "在线Cron表达式生成器")
+## 关于我
-- [在线工具 - 程序员的工具箱](http://tool.lu/ "在线工具 - 程序员的工具箱")
-- [spring boot官方脚手架](https://start.spring.io/ "spring boot官方脚手架")
+@[小莫](https://xiaomo.info):热爱开源、追求新潮的开发者,习惯以 GitHub 的 issue 驱动方式组织自己的项目。熟悉游戏开发和 Web 开发,目前任 RPG 服务端主程。也是个喜欢二次元的死宅,爱动漫,略懂日语。
+欢迎联系一起进步:
-### 问题反馈
-1. 欢迎提[issue](https://github.com/houko/SpringBootUnity/issues)一起完善这个项目。
-2. QQ: 83387856
-4. 个人主站: https://xiaomo.info
+- Issue:
+- 个人主站:
+- QQ:83387856
+## 相关链接
-## [License](LICENSE "MIT")
+- [Spring Boot 官方脚手架](https://start.spring.io/)
+- [Spring Boot 官方文档](https://docs.spring.io/spring-boot/index.html)
+- [在线 Cron 表达式生成器](https://cron.qqe2.com/)
- MIT License
-
- Copyright (c) 2022 Peng Hu
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
+## License
+[MIT](LICENSE) © Peng Hu
diff --git a/async/src/main/java/info/xiaomo/anysc/AsyncMain.java b/async/src/main/java/info/xiaomo/async/AsyncMain.java
similarity index 97%
rename from async/src/main/java/info/xiaomo/anysc/AsyncMain.java
rename to async/src/main/java/info/xiaomo/async/AsyncMain.java
index 1e550e2f..ae2aefe5 100644
--- a/async/src/main/java/info/xiaomo/anysc/AsyncMain.java
+++ b/async/src/main/java/info/xiaomo/async/AsyncMain.java
@@ -1,4 +1,4 @@
-package info.xiaomo.anysc;
+package info.xiaomo.async;
import org.springframework.boot.SpringApplication;
diff --git a/async/src/main/java/info/xiaomo/anysc/controller/TestController.java b/async/src/main/java/info/xiaomo/async/controller/TestController.java
similarity index 97%
rename from async/src/main/java/info/xiaomo/anysc/controller/TestController.java
rename to async/src/main/java/info/xiaomo/async/controller/TestController.java
index 0817a3a8..5c0623a1 100644
--- a/async/src/main/java/info/xiaomo/anysc/controller/TestController.java
+++ b/async/src/main/java/info/xiaomo/async/controller/TestController.java
@@ -1,6 +1,6 @@
-package info.xiaomo.anysc.controller;
+package info.xiaomo.async.controller;
-import info.xiaomo.anysc.task.AsyncTask;
+import info.xiaomo.async.task.AsyncTask;
import info.xiaomo.core.base.BaseController;
import info.xiaomo.core.base.Result;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/async/src/main/java/info/xiaomo/anysc/task/AsyncTask.java b/async/src/main/java/info/xiaomo/async/task/AsyncTask.java
similarity index 97%
rename from async/src/main/java/info/xiaomo/anysc/task/AsyncTask.java
rename to async/src/main/java/info/xiaomo/async/task/AsyncTask.java
index 73ac1fc5..1fa2fcb7 100644
--- a/async/src/main/java/info/xiaomo/anysc/task/AsyncTask.java
+++ b/async/src/main/java/info/xiaomo/async/task/AsyncTask.java
@@ -1,4 +1,4 @@
-package info.xiaomo.anysc.task;
+package info.xiaomo.async.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
diff --git a/changeLog.md b/changeLog.md
index 6f012db4..2f264f76 100644
--- a/changeLog.md
+++ b/changeLog.md
@@ -1,6 +1,6 @@
- 2017-09-02 api模块: 添加swagger-bootstrap-ui,和原有ui并行存在。
http://localhost:8080 默认UI
-http://localhost:808/doc.html bootstrap-ui
+http://localhost:8080/doc.html bootstrap-ui
```
1. spring boot版本从1.4.3更新到1.5.6
@@ -42,4 +42,19 @@ http://localhost:808/doc.html bootstrap-ui
```

-
\ No newline at end of file
+
+- 2026-09-09 更新记录
+
+```
+1. 升级到 spring boot 4.1.1, jdk 升级到 21, 全部依赖更新到最新版本
+2. javax.* 迁移到 jakarta.*(persistence/servlet/mail/websocket)
+3. api 文档从已停止维护的 springfox 迁移到 springdoc-openapi, 注解升级到 OpenAPI 3
+4. 移除 swagger-bootstrap-ui / knife4j(最新版仍锁定 spring boot 3, 无法与 4 共存),
+ 上文提到的 /doc.html 界面不再提供, 改用 springdoc 自带的 /swagger-ui.html
+5. security 模块改用 SecurityFilterChain 组件式配置, 替换已移除的 WebSecurityConfigurerAdapter
+6. fastjson 迁移到 fastjson2, jackson 升级到 3.x, poi 升级到 5.x, dom4j 迁移到 org.dom4j
+7. 新增 GitHub Actions 构建 CI(此前仓库没有任何会编译代码的 CI)
+8. 修正包名拼写: info.xiaomo.anysc -> async, info.xiaomo.core.untils -> utils
+9. 打开此前被全局关闭的测试执行(surefire skipTests)
+10. 清理 oauth.properties 中提交进仓库的第三方登录密钥, 换成占位符
+```
diff --git a/core/src/main/java/info/xiaomo/core/filter/CustomDateSerializerFilter.java b/core/src/main/java/info/xiaomo/core/filter/CustomDateSerializerFilter.java
index d1e733ba..3405e8f9 100644
--- a/core/src/main/java/info/xiaomo/core/filter/CustomDateSerializerFilter.java
+++ b/core/src/main/java/info/xiaomo/core/filter/CustomDateSerializerFilter.java
@@ -1,6 +1,6 @@
package info.xiaomo.core.filter;
-import info.xiaomo.core.untils.TimeUtil;
+import info.xiaomo.core.utils.TimeUtil;
import tools.jackson.core.JsonGenerator;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.ValueSerializer;
diff --git a/core/src/main/java/info/xiaomo/core/untils/AuthUtil.java b/core/src/main/java/info/xiaomo/core/utils/AuthUtil.java
similarity index 95%
rename from core/src/main/java/info/xiaomo/core/untils/AuthUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/AuthUtil.java
index 776f9a1a..b46b9b3f 100644
--- a/core/src/main/java/info/xiaomo/core/untils/AuthUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/AuthUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import jakarta.servlet.http.HttpSession;
diff --git a/core/src/main/java/info/xiaomo/core/untils/CastUtil.java b/core/src/main/java/info/xiaomo/core/utils/CastUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/CastUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/CastUtil.java
index a3c19f4c..e3bf4938 100644
--- a/core/src/main/java/info/xiaomo/core/untils/CastUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/CastUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import java.io.*;
import java.nio.ByteBuffer;
diff --git a/core/src/main/java/info/xiaomo/core/untils/CharUtil.java b/core/src/main/java/info/xiaomo/core/utils/CharUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/CharUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/CharUtil.java
index 17b3e973..93259892 100644
--- a/core/src/main/java/info/xiaomo/core/untils/CharUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/CharUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
diff --git a/core/src/main/java/info/xiaomo/core/untils/DownUtil.java b/core/src/main/java/info/xiaomo/core/utils/DownUtil.java
similarity index 98%
rename from core/src/main/java/info/xiaomo/core/untils/DownUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/DownUtil.java
index 3f6d64e0..b31ea20f 100644
--- a/core/src/main/java/info/xiaomo/core/untils/DownUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/DownUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import lombok.extern.slf4j.Slf4j;
diff --git a/core/src/main/java/info/xiaomo/core/untils/ExcelUtil.java b/core/src/main/java/info/xiaomo/core/utils/ExcelUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/ExcelUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/ExcelUtil.java
index f2c580c0..8d4fc80b 100644
--- a/core/src/main/java/info/xiaomo/core/untils/ExcelUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/ExcelUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
diff --git a/core/src/main/java/info/xiaomo/core/untils/FileUtil.java b/core/src/main/java/info/xiaomo/core/utils/FileUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/FileUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/FileUtil.java
index d0297bf5..d3125fe6 100644
--- a/core/src/main/java/info/xiaomo/core/untils/FileUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/FileUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import info.xiaomo.core.constant.FileConst;
import info.xiaomo.core.constant.SymbolConst;
diff --git a/core/src/main/java/info/xiaomo/core/untils/HtmlUtil.java b/core/src/main/java/info/xiaomo/core/utils/HtmlUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/HtmlUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/HtmlUtil.java
index 975e56ac..ca747d45 100644
--- a/core/src/main/java/info/xiaomo/core/untils/HtmlUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/HtmlUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
diff --git a/core/src/main/java/info/xiaomo/core/untils/HttpUtil.java b/core/src/main/java/info/xiaomo/core/utils/HttpUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/HttpUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/HttpUtil.java
index 17cc0b8a..acf56a6f 100644
--- a/core/src/main/java/info/xiaomo/core/untils/HttpUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/HttpUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import org.apache.commons.lang3.StringUtils;
diff --git a/core/src/main/java/info/xiaomo/core/untils/IDUtil.java b/core/src/main/java/info/xiaomo/core/utils/IDUtil.java
similarity index 97%
rename from core/src/main/java/info/xiaomo/core/untils/IDUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/IDUtil.java
index edeb571b..7e12cfa2 100644
--- a/core/src/main/java/info/xiaomo/core/untils/IDUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/IDUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/core/src/main/java/info/xiaomo/core/untils/LunarCalendarUtil.java b/core/src/main/java/info/xiaomo/core/utils/LunarCalendarUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/LunarCalendarUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/LunarCalendarUtil.java
index 5a30f3af..64c5ba87 100644
--- a/core/src/main/java/info/xiaomo/core/untils/LunarCalendarUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/LunarCalendarUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import java.util.Calendar;
import java.util.Date;
diff --git a/core/src/main/java/info/xiaomo/core/untils/MailUtil.java b/core/src/main/java/info/xiaomo/core/utils/MailUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/MailUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/MailUtil.java
index 1d0712d9..bd91d7d5 100644
--- a/core/src/main/java/info/xiaomo/core/untils/MailUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/MailUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import jakarta.mail.*;
import jakarta.mail.internet.InternetAddress;
diff --git a/core/src/main/java/info/xiaomo/core/untils/Md5Util.java b/core/src/main/java/info/xiaomo/core/utils/Md5Util.java
similarity index 98%
rename from core/src/main/java/info/xiaomo/core/untils/Md5Util.java
rename to core/src/main/java/info/xiaomo/core/utils/Md5Util.java
index 3a14c314..309ab9ec 100644
--- a/core/src/main/java/info/xiaomo/core/untils/Md5Util.java
+++ b/core/src/main/java/info/xiaomo/core/utils/Md5Util.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import java.security.MessageDigest;
diff --git a/core/src/main/java/info/xiaomo/core/untils/PropsUtil.java b/core/src/main/java/info/xiaomo/core/utils/PropsUtil.java
similarity index 94%
rename from core/src/main/java/info/xiaomo/core/untils/PropsUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/PropsUtil.java
index 7a202818..b4d6d8f3 100644
--- a/core/src/main/java/info/xiaomo/core/untils/PropsUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/PropsUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import java.io.FileInputStream;
import java.io.InputStream;
diff --git a/core/src/main/java/info/xiaomo/core/untils/RandomUtil.java b/core/src/main/java/info/xiaomo/core/utils/RandomUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/RandomUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/RandomUtil.java
index d1dd3b50..c3007d6d 100644
--- a/core/src/main/java/info/xiaomo/core/untils/RandomUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/RandomUtil.java
@@ -4,7 +4,7 @@
* 创建日期: 2015年2月5日 下午2:38:48
* 创建作者: 杨 强 <281455776@qq.com>
*/
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
diff --git a/core/src/main/java/info/xiaomo/core/untils/RegExUtil.java b/core/src/main/java/info/xiaomo/core/utils/RegExUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/RegExUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/RegExUtil.java
index 976c2712..5f24b994 100644
--- a/core/src/main/java/info/xiaomo/core/untils/RegExUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/RegExUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import org.apache.commons.lang3.StringUtils;
diff --git a/core/src/main/java/info/xiaomo/core/untils/SerializeUtil.java b/core/src/main/java/info/xiaomo/core/utils/SerializeUtil.java
similarity index 98%
rename from core/src/main/java/info/xiaomo/core/untils/SerializeUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/SerializeUtil.java
index f6be3ed2..3dcac2de 100644
--- a/core/src/main/java/info/xiaomo/core/untils/SerializeUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/SerializeUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import java.io.*;
import java.nio.charset.StandardCharsets;
diff --git a/core/src/main/java/info/xiaomo/core/untils/SqlUtil.java b/core/src/main/java/info/xiaomo/core/utils/SqlUtil.java
similarity index 98%
rename from core/src/main/java/info/xiaomo/core/untils/SqlUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/SqlUtil.java
index 7e69e630..66e53e00 100644
--- a/core/src/main/java/info/xiaomo/core/untils/SqlUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/SqlUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import org.apache.commons.lang3.StringUtils;
diff --git a/core/src/main/java/info/xiaomo/core/untils/StringUtil.java b/core/src/main/java/info/xiaomo/core/utils/StringUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/StringUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/StringUtil.java
index b4a65ee0..78f27dd1 100644
--- a/core/src/main/java/info/xiaomo/core/untils/StringUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/StringUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import org.apache.commons.lang3.StringUtils;
diff --git a/core/src/main/java/info/xiaomo/core/untils/TimeUtil.java b/core/src/main/java/info/xiaomo/core/utils/TimeUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/TimeUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/TimeUtil.java
index 10b09e5e..aab097dc 100644
--- a/core/src/main/java/info/xiaomo/core/untils/TimeUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/TimeUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import info.xiaomo.core.constant.SymbolConst;
diff --git a/core/src/main/java/info/xiaomo/core/untils/TokenUtil.java b/core/src/main/java/info/xiaomo/core/utils/TokenUtil.java
similarity index 98%
rename from core/src/main/java/info/xiaomo/core/untils/TokenUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/TokenUtil.java
index 59d4e317..17a05852 100644
--- a/core/src/main/java/info/xiaomo/core/untils/TokenUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/TokenUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import com.alibaba.fastjson2.JSONObject;
import info.xiaomo.core.constant.SymbolConst;
diff --git a/core/src/main/java/info/xiaomo/core/untils/XmlUtil.java b/core/src/main/java/info/xiaomo/core/utils/XmlUtil.java
similarity index 99%
rename from core/src/main/java/info/xiaomo/core/untils/XmlUtil.java
rename to core/src/main/java/info/xiaomo/core/utils/XmlUtil.java
index a62f4c4a..4bb8306d 100644
--- a/core/src/main/java/info/xiaomo/core/untils/XmlUtil.java
+++ b/core/src/main/java/info/xiaomo/core/utils/XmlUtil.java
@@ -1,4 +1,4 @@
-package info.xiaomo.core.untils;
+package info.xiaomo.core.utils;
import com.alibaba.fastjson2.JSON;
import org.dom4j.*;
diff --git a/core/src/main/resources/config/oauth.properties b/core/src/main/resources/config/oauth.properties
index c1010125..c94cc757 100644
--- a/core/src/main/resources/config/oauth.properties
+++ b/core/src/main/resources/config/oauth.properties
@@ -1,28 +1,30 @@
-## qq openid
-openid_qq=101292993
-openkey_qq=e1bee0c32c149b66a295f295646ad092
+# 第三方登录的应用凭据。请填入自己在各平台申请的值, 不要把真实密钥提交进版本库。
+# 建议改为从环境变量注入, 例如 openkey_qq=${OAUTH_QQ_SECRET}
+
+openid_qq=your_qq_app_id
+openkey_qq=your_qq_app_secret
redirect_qq=http://static.xiaomo.info/qq/callback
-## sina openid
-openid_sina=4193705357
-openkey_sina=bc7bbdfe92be06b42b38206f8bca3645
+
+openid_sina=your_sina_app_id
+openkey_sina=your_sina_app_secret
redirect_sina=http://static.xiaomo.info/sina/callback
-## baidu openid
-openid_baidu=xwKOgtKjbbrn9dOb7ZkGrAo5
-openkey_baidu=dNlKN4vVqgZvROrWW8twc4wESGWkSfF8
+
+openid_baidu=your_baidu_app_id
+openkey_baidu=your_baidu_app_secret
redirect_baidu=http://static.xiaomo.info/baidu/callback
-## renren openid
-openid_renren=80cd6ab8bc924c97b78e06568196456e
-openkey_renren=51aab0e2633f43a2aeda89f299a7b4f8
+
+openid_renren=your_renren_app_id
+openkey_renren=your_renren_app_secret
redirect_renren=http://static.xiaomo.info/renren/callback
-## osc openid
-openid_osc=R6XS1Qnhist6jy5UABer
-openkey_osc=llvILNi5ThQj2YwgbM6qx7BOEKIfJjjM
+
+openid_osc=your_osc_app_id
+openkey_osc=your_osc_app_secret
redirect_osc=http://static.xiaomo.info/osc/callback
-## douban openid
-openid_douban=04e962ea4e22c5980ebc28beea6850c8
-openkey_douban=d7ae6ac47ddf75e2
+
+openid_douban=your_douban_app_id
+openkey_douban=your_douban_app_secret
redirect_douban=http://static.xiaomo.info/douban/callback
-## github openid `no tested`
+
openid_github=
openkey_github=
-redirect_github=
\ No newline at end of file
+redirect_github=
diff --git a/crawler/src/main/java/info/xiaomo/crawler/schedule/ScheduledTasks.java b/crawler/src/main/java/info/xiaomo/crawler/schedule/ScheduledTasks.java
index 1d43fcbe..99660f09 100644
--- a/crawler/src/main/java/info/xiaomo/crawler/schedule/ScheduledTasks.java
+++ b/crawler/src/main/java/info/xiaomo/crawler/schedule/ScheduledTasks.java
@@ -1,6 +1,6 @@
package info.xiaomo.crawler.schedule;
-import info.xiaomo.core.untils.DownUtil;
+import info.xiaomo.core.utils.DownUtil;
import info.xiaomo.crawler.model.ShikigamiModel;
import info.xiaomo.crawler.service.ShikigamaService;
import info.xiaomo.crawler.spider.OnnmyoujiSpider;
diff --git a/crawler/src/main/java/info/xiaomo/crawler/spider/OnnmyoujiSpider.java b/crawler/src/main/java/info/xiaomo/crawler/spider/OnnmyoujiSpider.java
index 2423e44a..f3a2ac86 100644
--- a/crawler/src/main/java/info/xiaomo/crawler/spider/OnnmyoujiSpider.java
+++ b/crawler/src/main/java/info/xiaomo/crawler/spider/OnnmyoujiSpider.java
@@ -1,6 +1,6 @@
package info.xiaomo.crawler.spider;
-import info.xiaomo.core.untils.HttpUtil;
+import info.xiaomo.core.utils.HttpUtil;
import info.xiaomo.crawler.model.ShikigamiModel;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
diff --git a/pom.xml b/pom.xml
index c8804fac..6d701dc2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -227,9 +227,6 @@
org.apache.maven.plugins
maven-surefire-plugin
${surefire-plugin.version}
-
- true
-
diff --git a/rabbitmq/src/test/java/info/xiaomo/rabbitmq/RabbitMqTests.java b/rabbitmq/src/test/java/info/xiaomo/rabbitmq/RabbitMqTests.java
new file mode 100644
index 00000000..d0a5533d
--- /dev/null
+++ b/rabbitmq/src/test/java/info/xiaomo/rabbitmq/RabbitMqTests.java
@@ -0,0 +1,27 @@
+package info.xiaomo.rabbitmq;
+
+import info.xiaomo.rabbitmq.config.Sender;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+/**
+ * 该测试需要一台可连接的 RabbitMQ, 连接信息见 config/application.properties。
+ * 本地起好 broker 后去掉 @Disabled 即可运行。
+ *
+ * @author : xiaomo
+ */
+@SpringBootTest(classes = RabbitMqMain.class)
+@Disabled("需要一个运行中的 RabbitMQ 实例")
+class RabbitMqTests {
+
+ @Autowired
+ private Sender sender;
+
+ @Test
+ void hello() {
+ sender.send();
+ }
+
+}
diff --git a/rabbitmq/src/test/java/test/RabbitMqTests.java b/rabbitmq/src/test/java/test/RabbitMqTests.java
deleted file mode 100644
index 1e2ddab8..00000000
--- a/rabbitmq/src/test/java/test/RabbitMqTests.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package test;
-
-import info.xiaomo.rabbitmq.config.Sender;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-
-public class RabbitMqTests {
-
- @Autowired()
- private Sender sender;
-
- @Test
- public void hello() throws Exception {
- sender.send();
- }
-
-}
diff --git a/socket/src/main/java/info/xiaomo/chat/socket/MyWebSocket.java b/socket/src/main/java/info/xiaomo/chat/socket/MyWebSocket.java
index 8d6dee18..92bb7e02 100644
--- a/socket/src/main/java/info/xiaomo/chat/socket/MyWebSocket.java
+++ b/socket/src/main/java/info/xiaomo/chat/socket/MyWebSocket.java
@@ -1,7 +1,7 @@
package info.xiaomo.chat.socket;
-import info.xiaomo.core.untils.HtmlUtil;
-import info.xiaomo.core.untils.TimeUtil;
+import info.xiaomo.core.utils.HtmlUtil;
+import info.xiaomo.core.utils.TimeUtil;
import lombok.Data;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/website/src/main/java/info/xiaomo/website/controller/AdminUserController.java b/website/src/main/java/info/xiaomo/website/controller/AdminUserController.java
index c6c7780e..4e9f398f 100644
--- a/website/src/main/java/info/xiaomo/website/controller/AdminUserController.java
+++ b/website/src/main/java/info/xiaomo/website/controller/AdminUserController.java
@@ -11,8 +11,8 @@
import info.xiaomo.core.base.Result;
import info.xiaomo.core.constant.CodeConst;
import info.xiaomo.core.exception.UserNotFoundException;
-import info.xiaomo.core.untils.Md5Util;
-import info.xiaomo.core.untils.RandomUtil;
+import info.xiaomo.core.utils.Md5Util;
+import info.xiaomo.core.utils.RandomUtil;
import info.xiaomo.website.model.AdminModel;
import info.xiaomo.website.service.AdminUserService;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/website/src/main/java/info/xiaomo/website/controller/UserController.java b/website/src/main/java/info/xiaomo/website/controller/UserController.java
index f51720d8..7678ef35 100644
--- a/website/src/main/java/info/xiaomo/website/controller/UserController.java
+++ b/website/src/main/java/info/xiaomo/website/controller/UserController.java
@@ -10,10 +10,10 @@
import info.xiaomo.core.constant.CodeConst;
import info.xiaomo.core.constant.GenderConst;
import info.xiaomo.core.exception.UserNotFoundException;
-import info.xiaomo.core.untils.MailUtil;
-import info.xiaomo.core.untils.Md5Util;
-import info.xiaomo.core.untils.RandomUtil;
-import info.xiaomo.core.untils.TimeUtil;
+import info.xiaomo.core.utils.MailUtil;
+import info.xiaomo.core.utils.Md5Util;
+import info.xiaomo.core.utils.RandomUtil;
+import info.xiaomo.core.utils.TimeUtil;
import info.xiaomo.website.model.UserModel;
import info.xiaomo.website.service.UserService;
import org.hibernate.service.spi.ServiceException;
diff --git a/website/src/main/java/info/xiaomo/website/util/MailUtil.java b/website/src/main/java/info/xiaomo/website/util/MailUtil.java
index fb04cb15..21d65499 100644
--- a/website/src/main/java/info/xiaomo/website/util/MailUtil.java
+++ b/website/src/main/java/info/xiaomo/website/util/MailUtil.java
@@ -2,7 +2,7 @@
import freemarker.template.Configuration;
import freemarker.template.Template;
-import info.xiaomo.core.untils.TimeUtil;
+import info.xiaomo.core.utils.TimeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;