1. 项目背景与技术选型
江理工文档管理系统是一个典型的Java Web毕业设计项目,采用SpringBoot+Vue前后端分离架构。这种技术组合在近年来的企业级应用开发中已成为主流方案,特别适合高校毕业设计展示学生的全栈开发能力。
SpringBoot作为后端框架的选择主要基于以下考虑:
- 自动配置特性大幅减少了XML配置工作量
- 内嵌Tomcat容器简化了部署流程
- Starter依赖机制让技术集成变得简单
- 完善的文档和社区支持降低了学习成本
Vue.js作为前端框架的优势体现在:
- 响应式数据绑定简化了DOM操作
- 组件化开发提高代码复用率
- Vue CLI提供了完善的项目脚手架
- 丰富的生态系统(Vuex、Vue Router等)
2. 系统架构设计
2.1 整体架构图
code复制[前端] Vue.js + ElementUI
↑ HTTP/HTTPS
[后端] SpringBoot + MyBatis
↑ JDBC
[数据库] MySQL
2.2 核心功能模块
- 用户认证模块(JWT实现)
- 文档上传下载模块
- 文档分类管理模块
- 文档检索模块
- 权限控制模块
- 操作日志模块
3. 数据库设计与实现
3.1 主要数据表结构
sql复制-- 用户表
CREATE TABLE `sys_user` (
`user_id` int NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
`real_name` varchar(50) DEFAULT NULL,
`dept_id` int DEFAULT NULL,
`email` varchar(100) DEFAULT NULL,
`mobile` varchar(20) DEFAULT NULL,
`status` tinyint DEFAULT '1',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`user_id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 文档表
CREATE TABLE `doc_file` (
`file_id` int NOT NULL AUTO_INCREMENT,
`file_name` varchar(255) NOT NULL,
`file_path` varchar(500) NOT NULL,
`file_size` bigint NOT NULL,
`file_type` varchar(50) DEFAULT NULL,
`category_id` int DEFAULT NULL,
`user_id` int NOT NULL,
`download_count` int DEFAULT '0',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`file_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.2 索引优化建议
- 在
doc_file表的category_id和user_id字段添加普通索引 - 对
sys_user表的username字段保持唯一索引 - 大文本字段考虑使用TEXT类型并单独建表
4. 后端关键实现
4.1 SpringBoot配置要点
yaml复制# application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/doc_manage?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
servlet:
multipart:
max-file-size: 50MB
max-request-size: 100MB
mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
4.2 文件上传接口实现
java复制@RestController
@RequestMapping("/api/file")
public class FileController {
@PostMapping("/upload")
public Result upload(@RequestParam("file") MultipartFile file,
@RequestParam(required = false) Integer categoryId) {
try {
// 校验文件大小
if (file.getSize() > 50 * 1024 * 1024) {
return Result.error("文件大小不能超过50MB");
}
// 生成存储路径
String originalFilename = file.getOriginalFilename();
String fileExt = originalFilename.substring(originalFilename.lastIndexOf("."));
String newFileName = UUID.randomUUID() + fileExt;
String filePath = "/upload/" + newFileName;
// 保存文件
File dest = new File(filePath);
file.transferTo(dest);
// 保存记录到数据库
DocFile docFile = new DocFile();
docFile.setFileName(originalFilename);
docFile.setFilePath(filePath);
docFile.setFileSize(file.getSize());
docFile.setFileType(file.getContentType());
docFile.setCategoryId(categoryId);
docFile.setUserId(SecurityUtils.getCurrentUserId());
fileService.save(docFile);
return Result.success(docFile);
} catch (Exception e) {
log.error("文件上传失败", e);
return Result.error("上传失败:" + e.getMessage());
}
}
}
5. 前端关键实现
5.1 Vue项目结构
code复制src/
├── api/ # 接口定义
├── assets/ # 静态资源
├── components/ # 公共组件
├── router/ # 路由配置
├── store/ # Vuex状态管理
├── utils/ # 工具函数
├── views/ # 页面组件
│ ├── document/ # 文档管理
│ ├── system/ # 系统管理
│ └── ...
└── App.vue # 根组件
5.2 文件上传组件实现
vue复制<template>
<el-upload
class="upload-demo"
action=""
:auto-upload="false"
:on-change="handleChange"
:show-file-list="false"
>
<el-button type="primary">选择文件</el-button>
<div slot="tip" class="el-upload__tip">
支持扩展名:.doc/.docx/.pdf/.ppt/.pptx/.xls/.xlsx,单文件不超过50MB
</div>
</el-upload>
</template>
<script>
import { uploadFile } from '@/api/document'
export default {
methods: {
async handleChange(file) {
const formData = new FormData()
formData.append('file', file.raw)
formData.append('categoryId', this.categoryId)
try {
const res = await uploadFile(formData)
this.$emit('success', res.data)
this.$message.success('上传成功')
} catch (e) {
this.$message.error('上传失败:' + e.message)
}
}
}
}
</script>
6. 系统部署方案
6.1 开发环境部署
- 后端启动:
bash复制mvn spring-boot:run
- 前端启动:
bash复制npm run serve
6.2 生产环境部署
推荐使用Docker容器化部署:
dockerfile复制# 后端Dockerfile
FROM openjdk:8-jdk-alpine
VOLUME /tmp
ADD target/doc-manage.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
# 前端Dockerfile
FROM nginx:alpine
COPY dist/ /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/conf.d/default.conf
6.3 Nginx配置示例
nginx复制server {
listen 80;
server_name yourdomain.com;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api/ {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
7. 毕业设计扩展建议
- 增加全文检索功能:集成Elasticsearch实现文档内容检索
- 添加版本控制:实现文档的版本管理功能
- 集成第三方登录:支持微信、QQ等第三方登录
- 实现在线预览:集成Office Online Server或OnlyOffice
- 增加审批流程:使用Activiti实现文档审批流程
提示:在开发过程中,建议使用Git进行版本控制,保持良好的提交记录。可以按照功能模块划分分支,如
feature/user-auth、feature/file-upload等。
8. 常见问题解决方案
- 跨域问题:
java复制@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.maxAge(3600);
}
}
- 文件下载中文乱码:
java复制@GetMapping("/download/{fileId}")
public void download(@PathVariable Integer fileId,
HttpServletResponse response) throws IOException {
DocFile file = fileService.getById(fileId);
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode(file.getFileName(), "UTF-8"));
Files.copy(Paths.get(file.getFilePath()), response.getOutputStream());
}
- Vue页面刷新404:
在路由配置中添加:
javascript复制const router = new VueRouter({
mode: 'history',
routes,
scrollBehavior(to, from, savedPosition) {
return { x: 0, y: 0 }
}
})
9. 性能优化建议
- 使用Redis缓存高频访问的文档信息
- 对大文件上传实现分片上传
- 对文档列表接口实现分页查询
- 使用Nginx开启Gzip压缩
- 对静态资源配置长期缓存
- 使用Webpack的SplitChunks优化前端打包
10. 安全防护措施
- 密码加密存储(BCrypt)
- JWT Token设置合理过期时间
- 文件上传限制文件类型
- 接口参数校验(使用Hibernate Validator)
- 防止SQL注入(MyBatis使用#{})
- XSS防护(前端使用vue-sanitize)
在实际开发中,我发现最容易忽视的是文件上传的安全控制。除了检查文件扩展名,还应该检查文件魔数(Magic Number)来验证真实文件类型。例如PDF文件的开头应该是"%PDF",而不仅仅是依赖文件后缀名判断。
