需求原文:后端目前没有必须使用 Python 才能方便实现的功能,改为 SpringBoot 转写以方便跨平台部署。不删除当前后端代码,在新目录下写入。ORM 框架使用 MyBatis。
| 约束 | 说明 |
|---|---|
| 原 Python 后端保留 | backend/ 目录原样保留,不做任何修改;两套后端可在不同端口并行运行验证 |
| 新目录 | 全部 Java 代码写入 backend-java/,Maven 标准布局 |
| 前端零改动 | API 契约完全对齐 backend/openapi/openapi.yaml,前端仅在切换时改 base URL(或经 Nginx 反代不改) |
| 数据同库 | 复用同一 MySQL 库(Alembic 已建表,schema 以 Alembic 0016 head 为准),不另建库 |
| 文件存储共用 | 复用同一 DMS_STORAGE_ROOT,两套后端可直接读取对方写入的文件 |
| 端口错开 | Java 版默认 9346(Python 版 9345),避免并行验证冲突 |
| Python 依赖 | 实际用途(代码位置) | Java 对应方案 | 结论 |
|---|---|---|---|
| flask / flask-cors | Web 框架与 CORS | Spring Boot Web + CorsConfig | 直译 |
| Flask-SQLAlchemy / SQLAlchemy / PyMySQL | ORM 与 MySQL 驱动 | MyBatis + mysql-connector-j | 直译(SQL 为准) |
| alembic(迁移 0001~0016) | 表结构演进 | Flyway(baseline 对齐 0016,此后 Java 版独占演进) | 见 §4.3 |
| PyJWT(HS256) | 登录态令牌 | jjwt(同 DMS_JWT_SECRET、同算法) |
令牌互通 |
| argon2-cffi(Argon2id,PHC 串) | 密码哈希 | spring-security-crypto Argon2PasswordEncoder(可校验存量 PHC 串) |
存量密码直接可用 |
| pymupdf(fitz) | PDF 正文提取与预览(document_content_service / preview_service) | Apache PDFBox(PDFTextStripper / Loader) | 需回归验证提取差异 |
| python-docx | DOCX 正文提取 | Apache POI XWPFParagraph | 需回归验证 |
| olefile | 上传件 OLE 结构校验(storage/uploads) | Apache POI POIFSFileSystem | 直译 |
| LibreOffice subprocess | DOC→PDF 转换(document_converter) | ProcessBuilder(命令行不变,语言无关) | 直译 |
| langchain / langchain-openai / pypinyin | 代码中零引用(requirements.txt 残留依赖) | 无需对应 | 直接丢弃 |
| requests | 门户 HTTP 验签(portal_provider) | Spring RestClient |
直译 |
| PyYAML | openapi 装配期校验 | SnakeYAML(仅测试用) | 直译 |
| python-docx / tzdata 等 | — | JDK 内置 / 依赖自带 | — |
结论:无必须使用 Python 的功能,全部能力均有成熟 Java 对应,转写为纯工程翻译工作。
| 项 | 选择 | 版本 |
|---|---|---|
| 运行时 | Java | 17(LTS) |
| 框架 | Spring Boot | 3.3.x |
| ORM | MyBatis(mybatis-spring-boot-starter) | 3.0.x |
| 数据库驱动 | mysql-connector-j | 8.4.x |
| 迁移 | Flyway(flyway-core + flyway-mysql) | 随 Boot |
| JWT | jjwt-api/impl/jackson | 0.12.x |
| 密码哈希 | spring-security-crypto(仅用 Argon2PasswordEncoder,不引入完整 Security 过滤链) | 随 Boot |
| DOCX/OLE | Apache POI | 5.3.x |
| Apache PDFBox | 3.0.x | |
| 工具 | Lombok、HikariCP(Boot 默认) | — |
| 构建 | Maven + spring-boot-maven-plugin(单 jar,替代 PyInstaller) | — |
认证与授权沿用 Python 版自研方案(JWT 过滤器 + 注解式角色/权限校验),不启用 Spring Security 默认过滤链,保证行为与 Python 版逐条对齐。
backend/dms/common/response.py 一致:{code, message, data},成功 code="OK";backend/dms/common/errors.py 逐条移植为 DmsException(code, httpStatus, defaultMessage) + 子类;@RestControllerAdvice 转译为 INVALID_ARGUMENT,保证前端 errorCode 分支完全不变。DMS_JWT_SECRET、HS256、同 claims(sub/uid/role/authVersion/iat/exp),两套后端签发的令牌互相可验;auth_version 失效机制同款:改密/登出后令牌立即失效;Argon2PasswordEncoder 校验存量哈希;新设密码同样产出 PHC 串,Python 版亦能校验(双写期安全)。alembic_version 表(值 0016);baseline-on-migrate=true, baseline-version=0,V1__baseline_alembic_0016.sql 为空 DDL(仅占位,schema 已由 Alembic 建好),此后演进全部走 Flyway V2+;DMS_STORAGE_ROOT 等全部 DMS_* 环境变量名与语义逐一同名移植(见 backend/dms/config.py),.env 可直接复用;docs/{id}/...、预览缓存、正文缓存)按 backend/dms/storage/paths.py 原样复刻,保证两套后端互读。backend-java/
├── pom.xml
├── .env.example # 与 backend/.env.example 同键
└── src/main/
├── java/com/dms/
│ ├── DmsApplication.java
│ ├── config/ # CorsConfig、MyBatis 配置、环境变量装载(DmsProperties)
│ ├── common/ # 响应包络 ApiResponse、分页、业务异常体系、时间范围解析
│ ├── security/ # JwtFilter、JwtTokens、Argon2 密码、AuthContext、注解鉴权
│ ├── model/ # POJO 实体(对应 sys_user / sys_role / sys_organization /
│ │ # sys_category / doc_document / doc_relation / doc_permission /
│ │ # sys_audit_log / sys_ip_entry / sys_org_ip_assignment)
│ ├── mapper/ # MyBatis Mapper 接口 + resources/mapper/*.xml
│ ├── service/ # 业务服务,与 Python dms/services/* 一一对应
│ ├── storage/ # 上传落盘、路径、完整性校验、正文提取(POI/PDFBox)
│ └── api/v1/ # Controller:auth、portalAuth、users、roles、organizations、
│ # categories、documents、files、recycleBin、audit、
│ # ipEntries、uiDictionaries、runtimeConfig、health
├── resources/
│ ├── application.yml
│ ├── mapper/*.xml
│ ├── db/migration/ # Flyway
│ └── resources/ # ui-dictionaries / document-relation-presets(从 Python 版同步)
└── test/java/com/dms/ # 关键路径测试(auth、权限矩阵、文档生命周期)
每阶段完成后以「Python 版对应 pytest 用例 + 前端手工冒烟」双口径验证;前端指向 9346 冒烟通过后该阶段才算完成。
| 阶段 | 内容 | 主要产出 | 验证标准 | 预估 |
|---|---|---|---|---|
| 1 | 工程骨架 | pom、application.yml、ApiResponse、全局异常→错误码映射、CORS、健康检查、Flyway baseline、环境变量装载 | 启动无报错;GET /api/v1/health 200;非法请求返回包络错误码 |
1 天 |
| 2 | 认证与用户基础 | users 表 Mapper、login/logout/me、JWT、Argon2、IP 登录限制 | 前端可登录/登出/会话保持;存量账号密码可直接登录 | 2 天 |
| 3 | 门户跳转登录 | portal verify / setup-password、provider(http/mock/custom)、自动建号 | test_portal_auth.py 全部分支在 Java 版行为一致(mock 流程手工复测) |
1.5 天 |
| 4 | 组织 / 用户 / 角色管理 | organizations、users CRUD、roles 与权限矩阵、审计写入 | 后台管理页全功能可用;操作审计落库 | 3 天 |
| 5 | 分类与文档 | categories(含扁平模式)、documents CRUD、上下传、dms-storage 落盘、完整性校验、方案密码锁 | 文档全生命周期可用;与 Python 版互读对方存储文件 | 4 天 |
| 6 | 检索与正文 | 正文提取(PDFBox/POI)、search_text 回填、关键词/时间范围/全局检索、命中片段 | 检索结果与 Python 版抽样一致;提取差异肉眼可接受 | 3 天 |
| 7 | 权限引擎与关系面板 | permission_service、authorization_service、部门数据范围、挂载/解绑、回收站 | 权限矩阵逐格抽验;回收站恢复全约束生效 | 3 天 |
| 8 | 预览转换与审计统计 | 预览缓存、DOC→PDF(LibreOffice)、审计查询与统计 | 三类文件预览正常;审计统计口径一致 | 2 天 |
| 9 | 工具与部署 | seed 数据脚本、upgrade-db、打包(单 jar)、run.bat/run.sh、docs/ 运维手册 |
打包产物在干净机器可一键启动 | 2 天 |
合计约 18~21 个工作日。阶段 2 起每阶段收尾生成对比清单(Python 用例 → Java 行为结论)存入 docs/plans/SpringBoot转写验证记录.md。
| 风险 | 等级 | 对策 |
|---|---|---|
dms-storage 目录/文件名规则移植不一致导致互读失败 |
高 | 阶段 5 先写"Python 版建→Java 版读 / Java 版建→Python 版读"互读测试再接入业务 |
| PDFBox 与 PyMuPDF 正文提取细节差异(分页、空格、乱码) | 中 | 阶段 6 抽样对比提取文本;差异仅影响片段高亮,不影响正确性时记录已知差异 |
| Argon2 存量 PHC 校验兼容 | 中 | 阶段 2 首个测试即为"Python 版建号 → Java 版登录";spring-security-crypto 默认参数与 argon2-cffi 默认参数不同,但校验按 PHC 串内嵌参数执行,需实测确认 |
| Flyway 与 alembic_version 并存的管理混乱 | 中 | 立即冻结 Alembic 演进(§4.3);Java 版 schema 操作仅经 Flyway |
| LibreOffice 转换在 Java 进程管理的退出码/超时语义差异 | 低 | ProcessBuilder 显式 destroy + 同款超时秒数,阶段 8 实测 |
| openapi.yaml 装配期校验缺失导致契约漂移 | 低 | 阶段 1 搭 SnakeYAML 冒烟校验(仅测试期),后续按需补 |
docs/plans/SpringBoot转写验证记录.md)