1. 项目概述
在数字化转型浪潮下,档案管理系统的现代化改造已成为各类组织的刚需。这套基于SpringBoot+Vue3+MyBatis的档案管理系统,采用前后端分离架构,解决了传统档案管理中的三大痛点:纸质文档易损毁、检索效率低下以及权限管控薄弱。我在实际部署中发现,系统平均检索响应时间控制在200ms内,比传统方式提升近10倍。
系统核心功能模块包括:
- 多维度档案分类管理
- 基于RBAC的细粒度权限控制
- 操作日志全程追溯
- 高并发文件上传/下载
- 跨部门协作共享机制
技术选型上,后端采用SpringBoot 2.7.x提供RESTful API,前端使用Vue3+TypeScript构建响应式界面,MyBatis-Plus优化数据库操作,MySQL 8.0保障事务一致性。特别在权限设计上,我们采用JWT+Spring Security双重验证,有效防御越权访问。
2. 系统架构设计
2.1 技术栈深度解析
后端架构采用经典三层模式:
- Web层:SpringBoot处理HTTP请求,全局异常拦截器统一处理业务异常
- Service层:基于领域模型划分服务模块,事务注解保证数据一致性
- DAO层:MyBatis-Plus动态SQL生成,配合二级缓存提升查询效率
前端架构亮点:
- 使用Vue3 Composition API实现逻辑复用
- Pinia状态管理替代传统Vuex
- 动态路由配合后端权限数据实时生成菜单
- Axios拦截器自动处理Token刷新
数据库设计遵循三范式原则,同时针对高频查询做了适当反范式优化。比如在操作日志表中冗余了用户名信息,避免频繁联表查询。
2.2 核心数据模型
档案主表结构优化
sql复制CREATE TABLE `t_archive` (
`archive_id` BIGINT NOT NULL COMMENT '雪花算法ID',
`archive_name` VARCHAR(150) NOT NULL COMMENT '支持长文件名',
`file_hash` CHAR(32) NOT NULL COMMENT 'MD5去重',
`storage_path` VARCHAR(255) NOT NULL COMMENT 'OSS路径',
`file_size` BIGINT NOT NULL COMMENT '字节数',
`version` INT DEFAULT 1 COMMENT '乐观锁版本号',
PRIMARY KEY (`archive_id`),
UNIQUE KEY `idx_hash` (`file_hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
关键设计点:采用Snowflake算法生成分布式ID,通过文件哈希值实现秒传功能,utf8mb4_bin排序规则确保文件名大小写敏感
权限模型设计
采用RBAC扩展模型,引入用户组概念:
- 用户-角色:多对多关系
- 角色-权限:多对多关系
- 用户-用户组:多对多关系
- 权限粒度控制到按钮级别
java复制// 权限注解示例
@PreAuthorize("@pm.hasPermission('archive:delete')")
public void deleteArchive(Long archiveId) {
// 业务逻辑
}
3. 核心功能实现
3.1 文件上传下载模块
文件上传采用分片上传策略,前端使用Web Worker计算文件哈希,后端通过Redis实现秒传判断。关键代码逻辑:
java复制// 分片上传接口
@PostMapping("/upload/chunk")
public Result uploadChunk(@RequestParam MultipartFile file,
@RequestParam String chunkHash,
@RequestParam Integer chunkIndex) {
String tempPath = redisTemplate.opsForValue().get(chunkHash);
if (tempPath != null) {
return Result.success(tempPath); // 秒传返回
}
String path = fileStorageService.saveChunk(file, chunkIndex);
redisTemplate.opsForValue().set(chunkHash, path, 2, TimeUnit.HOURS);
return Result.success(path);
}
下载环节采用NIO零拷贝技术,大文件下载速度提升40%:
java复制@GetMapping("/download/{archiveId}")
public void downloadArchive(@PathVariable Long archiveId,
HttpServletResponse response) {
Archive archive = archiveService.getById(archiveId);
try (FileChannel channel = new FileInputStream(
new File(archive.getStoragePath())).getChannel()) {
response.setHeader("Content-Length", String.valueOf(archive.getFileSize()));
channel.transferTo(0, channel.size(), Channels.newChannel(response.getOutputStream()));
}
}
3.2 高级检索功能
基于Elasticsearch构建全文检索,支持:
- 语义化搜索(同义词扩展)
- 文件内容提取(Apache Tika)
- 组合条件过滤(创建时间、类型等)
检索DSL示例:
json复制{
"query": {
"bool": {
"must": [
{"match": {"content": {"query": "年度报告","fuzziness": "AUTO"}}},
{"range": {"create_time": {"gte": "2023-01-01"}}}
]
}
},
"highlight": {
"fields": {"content": {}}
}
}
4. 安全防护体系
4.1 认证授权方案
- 双Token机制:
- AccessToken:30分钟有效期
- RefreshToken:7天有效期,用于续期
- 动态权限加载:
java复制@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() { @Override public <O extends FilterSecurityInterceptor> O postProcess(O object) { object.setSecurityMetadataSource(customMetadataSource); return object; } }); } - 敏感操作二次验证:
- 关键操作需短信/邮箱验证
- 操作日志包含设备指纹信息
4.2 防攻击措施
- SQL注入:MyBatis参数化查询+正则过滤
- XSS:Jackson转义+前端DOMPurify处理
- CSRF:SameSite Cookie+自定义Header校验
- 暴力破解:Redis计数限流(5次/分钟)
5. 性能优化实践
5.1 数据库优化
- 索引策略:
- 组合索引遵循最左前缀原则
- 为操作日志表添加时间范围索引
sql复制ALTER TABLE t_operation_log ADD INDEX idx_user_operation (user_id, operation_type); - 查询优化:
- 禁用SELECT *
- 复杂查询使用@Transactional(readOnly = true)
- 批量操作使用rewriteBatchedStatements=true
5.2 缓存方案
采用多级缓存架构:
- 本地缓存:Caffeine缓存热点数据
yaml复制caffeine: spec: maximumSize=1000,expireAfterWrite=5m - 分布式缓存:Redis集群缓存共享数据
- 文件缓存:Nginx静态资源缓存
6. 部署与监控
6.1 容器化部署
Docker Compose编排示例:
yaml复制version: '3'
services:
backend:
image: archive-backend:1.0
environment:
- SPRING_PROFILES_ACTIVE=prod
ports:
- "8080:8080"
depends_on:
- redis
- mysql
frontend:
image: archive-frontend:1.0
ports:
- "80:80"
6.2 监控指标
- 业务指标:每日活跃用户、文件上传量
- 系统指标:JVM内存、SQL执行时间
- 异常监控:Sentinel熔断降级
7. 踩坑实录
-
文件并发上传问题:
- 现象:分片上传时出现文件损坏
- 原因:多个分片同时写入临时文件
- 解决:采用分段锁+临时目录隔离
-
MyBatis缓存污染:
- 现象:查询结果出现脏数据
- 原因:二级缓存未设置flushInterval
- 解决:配置缓存刷新间隔并添加@CacheNamespace注解
-
Vue3响应式丢失:
- 现象:数组更新后视图不刷新
- 原因:直接通过索引修改数组
- 解决:使用数组的变异方法或重新赋值
这套系统在实际落地过程中,我们团队总结出三条核心经验:第一,档案类系统要特别注重操作留痕;第二,文件存储必须考虑分布式方案;第三,权限体系要预留扩展接口。对于需要二次开发的同学,建议先从权限模块入手理解系统设计思想。