ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于WEB的考研资源共享系统源码实战:从解析到部署

基于WEB的考研资源共享系统源码实战:从解析到部署 简介基于WEB的考研资源共享系统源码包面向需要完成毕业设计、课程设计或期末大作业的计算机相关专业学生提供一套可直接运行的JavaWeb项目参考。源码覆盖用户注册登录、考研资料上传下载、学习笔记管理、后台分类维护等核心功能适合用来理解业务系统从需求分析到编码实现的全流程。压缩包为ZIP格式共660个文件含251个JavaScript脚本、88个class文件、47个CSS样式、44个Java源文件、33个HTML页面、12个JSP动态页面以及图片、字体等资源整体仅17.92MB目录结构清晰便于按模块查阅部署。已有133人学习下载可在本地环境快速运行并验证主要功能。阅读代码可学习Servlet控制层与DAO数据访问层的协作方式掌握前端与后端交互细节并在此基础上扩展新功能为论文撰写和答辩演示提供扎实素材。1. 基于WEB的考研资源共享系统源码先搞懂这类压缩包到底给你提供了什么“基于WEB的考研资源共享系统源码高分毕业设计.zip”这类压缩包在毕设圈一年会出现上千次名字点明了技术形态是 web 项目业务是考研资料分享后缀“高分毕业设计”则暗示它自带完整前后端、数据库脚本和文档。它解决的是考研资料分散在个人网盘、QQ群、公众号里的痛点把上传、分类、检索、下载、审核放到一个自己可控的网站里。适合毕设、课设、以及想搭校园考研资源库的技术爱好者。这篇文章按一线开发习惯拆解不假设你打开就是完整说明书而是教你怎么摸清它、跑起来、改得动。2. 功能拆解与技术选型先画清考研资源系统的边界再选不后悔的WEB技术栈2.1 用户、资源、管理三条主线功能边界不画清楚代码全是负债考研资源共享系统从产品层面看不是“做个网页能传文件”那么简单。答辩老师、验收方最关心的是三类角色能不能形成闭环游客和注册用户负责消费资源普通用户负责贡献资源管理员负责治理资源。我一般会先把角色和页面理成一张表角色核心权限典型页面游客浏览分类、搜索、查看资源详情首页、资源列表、搜索页普通用户注册登录、上传资料、下载资料、管理个人上传记录用户中心、上传页、我的上传管理员审核资源、管理分类、管理用户、查看统计数据后台管理、审核列表、数据看板这看起来简单但隐藏着几个容易被忽略的设计点。第一游客能不能下载很多毕设把下载按钮放出来点击后才提示“请先登录”这是最低成本的权限控制但答辩时容易被打问号。第二上传是否要审核如果不审核任何人都能传可执行文件、带毒压缩包说明缺少内容安全环节。第三下载次数和上传者积分怎么联动这是可以加分的“业务亮点”但不是所有源码都实现了。资源这一条线是最核心的。一个考研资源系统里常见的资源类型有公共课真题、专业课笔记、复试经验、调剂信息、视频课程、院校说明书。分类建议做成两级一级分类放“政治、英语、数学、专业课、复试调剂”二级分类挂“院校真题、学长笔记、视频讲解”这种。不要把所有资源直接平铺在一个大类下否则搜索和筛选都会很难看。管理这条线决定系统能不能真正运营。管理员不只是“删除资源”还要能处理用户举报、给驳回的资源填原因、调整分类排序。如果源码里只有简单的增删改查功能也算完整但你要有心理准备这类“高分毕设”往往是演示大于运营想要真正上线需要在审核和日志上补不少东西。2.2 技术选型看懂源码技术栈的四个判断点打开压缩包之前先想想为什么“基于WEB”这四个字不能直接告诉技术栈。早期毕设喜欢写“基于WEB的XX系统”底层可能是 Java WebJSP/Servlet也可能是 PHP、ASP.NET。后来 Spring Boot 和前后端分离流行起来同样叫“基于WEB”工程结构已经完全是另一套。拿到源码后我一般先看四个东西构建工具、语言版本、数据库脚本里的建表语句、前端有没有独立的 package.json。如果你是自己新写我建议优先选 Spring Boot 2.7 MyBatis-Plus MySQL 5.7/8.0 Vue3。原因很实际资料上传、下载进度、筛选搜索这类交互前后端分离比 JSP 好做Spring Boot 的原生 jar 包部署又比 Tomcat 里扔 war 包省事MyBatis-Plus 的代码量少毕业设计源码里出现频率也高网上能搜到的答案最多。如果你是拿到别人的 zip千万不要急着重构。先判断它的年代如果根目录里有pom.xml大概率是 Maven 工程如果有package.json前端是 Node 生态如果只有src和webapp可能是老式 Java Web 工程。老工程不是说不能跑而是要考虑 Tomcat 版本、JDK 版本、JSP 编译器的兼容性。我的建议是“能跑就不动”先按源码自带的技术栈启动等演示通过后再谈升级。前后端分离还有一个容易被忽略的坑端口和跨域。后端通常是 8080前端 Vite 开发服务器是 5173两者之间必须通过代理或 CORS 打通。很多源码的 README 里不会写后面第 5 章会单独讲。2.3 数据库设计用户表、资源文件表、审核状态字段的取舍不管源码是什么语言数据库设计都长得很像。核心表有四张用户表、分类表、资源表、下载记录表。如果设计得再完整一点还有评论表、积分流水表、公告表。先看一张最小可用的 SQL 设计CREATE TABLE t_user ( id int NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 登录名, password varchar(64) NOT NULL COMMENT 加密后的密码, nickname varchar(50) DEFAULT NULL, role tinyint NOT NULL DEFAULT 1 COMMENT 0管理员 1普通用户, points int NOT NULL DEFAULT 0 COMMENT 积分预留扩展, status tinyint NOT NULL DEFAULT 1 COMMENT 1正常 0禁用, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表; CREATE TABLE t_category ( id int NOT NULL AUTO_INCREMENT, name varchar(50) NOT NULL COMMENT 分类名称, parent_id int NOT NULL DEFAULT 0 COMMENT 父分类0表示一级分类, sort int NOT NULL DEFAULT 0, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT资源分类表; CREATE TABLE t_resource ( id int NOT NULL AUTO_INCREMENT, title varchar(100) NOT NULL COMMENT 资源标题, category_id int NOT NULL COMMENT 所属分类, file_type varchar(20) DEFAULT NULL COMMENT pdf/zip/rar/mp4等, file_size bigint DEFAULT 0 COMMENT 文件大小字节, file_path varchar(255) DEFAULT NULL COMMENT 相对路径不存完整磁盘路径, cover_image varchar(255) DEFAULT NULL COMMENT 封面图路径留空也可以, description text COMMENT 资源描述/摘要, uploader_id int NOT NULL COMMENT 上传用户ID, status tinyint NOT NULL DEFAULT 0 COMMENT 0待审核 1已发布 2已驳回, reject_reason varchar(255) DEFAULT NULL COMMENT 驳回原因, download_count int NOT NULL DEFAULT 0, create_time datetime DEFAULT NULL, PRIMARY KEY (id), KEY idx_category (category_id), KEY idx_status (status) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT考研资源表; CREATE TABLE t_download_record ( id int NOT NULL AUTO_INCREMENT, user_id int NOT NULL, resource_id int NOT NULL, download_time datetime DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT下载记录表;这里有几个取舍值得说明。t_resource里的file_path为什么不保存完整路径因为完整路径和部署服务器绑死换一台机器目录就全错了。更稳妥的做法是存相对路径比如/2025/03/21/uuid.pdf真正的根目录由配置文件里的upload.dir指定。password字段用 64 位长度是为了容纳 BCrypt 或 SHA-256 的哈希结果不要为了省空间设成 32 位。status默认 0 非常关键资源一上传就是待审核管理员审核通过后状态变成 1普通用户端只能看到状态为 1 的数据这样权限控制就收敛到了where status 1这一条 SQL 上。3. 本地跑通源码从解压到登录后台的最小步骤3.1 解压之后的“第一步”先找 pom.xml、application.yml 和 SQL 脚本这类 zip 包的打开方式很统一我习惯先用命令行解压不要双击进压缩软件慢慢拖因为后续要频繁操作路径unzip 基于WEB的考研资源共享系统源码(高分毕业设计).zip -d kaoyan-project cd kaoyan-project find . -maxdepth 2 -type f | head -50第一行解压到kaoyan-project目录第二行进入工程第三行列出两层以内的文件目的是在动手跑之前判断这到底是什么类型的 web 项目。看到pom.xml说明是 Maven 管理的 Java 工程看到package.json说明前端是 Node 工程看到doc/或sql/目录里面大概率有建表脚本和演示账号。千万不要一上来就mvn spring-boot:run因为你还没建库、没改密码后端启动后必然会在数据源阶段报错。如果找不到application.yml可以看application.properties如果老工程是 SSH 风格入口可能在web.xml或spring-mvc.xml里。找配置文件的顺序是src/main/resources→src/main/webapp/WEB-INF→ 根目录。找到一个即可不要每个都打开。重点确认三个信息数据库连接串、服务器端口、上传文件保存目录。这时你会看到一个很典型的工程骨架kaoyan-project/ ├── README.md ├── sql/ │ └── kaoyan.sql ├── backend/ │ ├── pom.xml │ └── src/main/resources/application.yml └── frontend/ ├── package.json └── src/很多源码包会把前后端放在同一个仓库里但不一定叫 backend/frontend也可能叫 server/web 或直接叫web。如果你的包只有单一目录那就用 find 再加深一层。识别完结构后第一步已经完成接下来建库导表。3.2 建库导表MySQL 初始化脚本与连接参数说明进入 sql 目录先看脚本里的建库语句是CREATE DATABASE还是直接建表。如果是直接建表说明你需要手动建库。为了减少排错我习惯在 MySQL 客户端里先建一个指定字符集的库再导入脚本mysql -uroot -p -e CREATE DATABASE IF NOT EXISTS kaoyan_resource DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; mysql -uroot -p kaoyan_resource sql/kaoyan.sql第一条命令创建kaoyan_resource库第二条把解压出来的 SQL 文件导入进去。导入结束后可以用mysql -uroot -p -e USE kaoyan_resource; SHOW TABLES;确认表是否生成。如果表数量很少连 t_resource 都没有说明导错了脚本或脚本版本不对回头检查文件里是否包含 DROP TABLE。千万注意SQL 里如果带着原有数据库名比如USE kaoyan;直接导入会自动切到那个库你的 kaoyan_resource 里可能还是空的。建库完成后去改后端配置文件。以 Spring Boot 的 application.yml 为例关键参数如下server: port: 8080 spring: datasource: url: jdbc:mysql://localhost:3306/kaoyan_resource?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 你自己的数据库密码 driver-class-name: com.mysql.cj.jdbc.Driver servlet: multipart: max-file-size: 200MB max-request-size: 500MB mybatis-plus: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true连接串里的serverTimezoneAsia/Shanghai和useSSLfalse是 MySQL 8 最常见的两个参数。前者解决时区报错后者避免本机没有证书时的误报。driver-class-name要注意MySQL 5 项目常用com.mysql.jdbc.DriverMySQL 8 必须用com.mysql.cj.jdbc.Driver。如果你本地装的是 MySQL 8但源码里写的是老驱动启动会说找不到类。multipart 两个参数决定上传文件大小上限考研资料里常出现几百 MB 的视频默认 1MB 会直接上传失败。3.3 后端启动与前端启动让首页在浏览器里出现后端是 Maven 工程时我先执行打包跳过测试再用 Java 命令启动比mvn spring-boot:run更容易看到完整日志cd backend mvn clean package -DskipTests java -jar target/kaoyan-resource-1.0.0.jar如果源码没有版本号你可以在 target 目录执行ls -lh *.jar找到实际 jar 名。日志出现Started Application in x.xxx seconds就说明后端起好了此时访问http://localhost:8080或http://localhost:8080/swagger-ui/index.html可以验证。如果启动到一半报数据库错95% 是刚才的账号密码和连接串问题回头再看第 5 章。前端如果是 Vue 工程命令相对固定。Node 版本是最大的不确定性所以我建议先配 npm 镜像再安装依赖cd frontend npm config set registry https://registry.npmmirror.com npm install npm run devnpm 镜像能明显加快安装速度但不是万能的。如果npm install报 node-gyp 或 node-sass 相关错误常见原因是本机 Node 版本太新比如 Node 18、20 遇到 node-sass 4.x。可以先node -v看版本再通过 nvm 切到 Node 14 或 16 重试。开发服务器起来后终端会打印Local: http://localhost:5173/浏览器打开这个地址。默认登录账号不要猜去 SQL 脚本里搜INSERT INTO t_user或t_user的前几行。很多毕设项目初始化的管理员是admin/admin123但也有源码改成admin/123456。找到后先登录后台再看资源列表里有没有初始数据。没有初始数据的话先去后台手工建一个分类再上传一个测试文件确认整条链路通不通。到这一步首页能打开、后台能登录本地跑通就算完成了。4. 核心功能落地文件上传、下载控制与资源审核怎么一步步做4.1 文件上传把考研资料存到磁盘而不是塞进数据库考研资料里有 PDF、Word、压缩包、视频单个文件从几百 KB 到几个 GB 都有。如果直接把文件塞进数据库 BLOB 字段听起来很美实际上会让数据库备份变得巨大、查询变慢、移植困难。正确做法是文件落到服务器磁盘数据库只存文件名、大小、相对路径。后端上传接口的代码骨架我一般这样写PostMapping(/api/resource/upload) public Result upload(RequestParam(file) MultipartFile file, RequestParam(title) String title, RequestParam(categoryId) Integer categoryId, HttpServletRequest request) { // 1. 从 session 中取出登录用户源码里也可能用 JWT Token User loginUser (User) request.getSession().getAttribute(loginUser); if (loginUser null) { return Result.error(请先登录); } // 2. 文件后缀白名单防止上传可执行文件 String originalName file.getOriginalFilename(); String ext originalName.substring(originalName.lastIndexOf(.) 1).toLowerCase(); ListString allowed Arrays.asList(pdf, zip, rar, doc, docx, ppt, pptx, mp4, jpg, png); if (!allowed.contains(ext)) { return Result.error(不支持的文件类型 ext); } // 3. 按日期分目录文件名使用 UUID避免重名覆盖 String dir uploadDir / LocalDate.now().toString().replace(-, ); File destDir new File(dir); if (!destDir.exists()) { destDir.mkdirs(); } String fileName UUID.randomUUID().toString().replace(-, ) . ext; String relativePath / LocalDate.now() / fileName; File dest new File(destDir, fileName); try { file.transferTo(dest); } catch (IOException e) { return Result.error(文件保存失败); } // 4. 保存资源元数据默认 status0 待审核 ResourceInfo res new ResourceInfo(); res.setTitle(title); res.setCategoryId(categoryId); res.setFileType(ext); res.setFileSize(file.getSize()); res.setFilePath(relativePath); res.setUploaderId(loginUser.getId()); res.setStatus(0); resourceService.save(res); return Result.success(上传成功等待管理员审核); }这段代码有三个参数和设计值得记住。file.transferTo(dest)是 Spring 封装好的输出方法比手动IOUtils.copy安全但要求目标父目录存在所以前面必须mkdirs()。UUID.randomUUID()生成的长文件名可以把中文文件名彻底替换掉避免下载时 URL 编码的麻烦同时防止张三上传的数学笔记.pdf覆盖李四的同名文件。relativePath只存相对路径配合全局配置uploadDir将来部署到 Linux 只要改一个配置项不用改代码。uploadDir这个变量从哪来我建议把它配置在 application.yml 里my-resource: upload-dir: /data/kaoyan/uploads然后通过Value(${my-resource.upload-dir})注入。本地开发时放在项目外部目录比如/data/kaoyan/uploads千万不要放在 target 或 src 下面否则mvn clean会把文件删掉。4.2 下载控制登录校验、下载次数统计与权限判定下载接口是考研资源系统里最容易被写坏的地方。最粗暴的写法是直接暴露文件目录用静态资源映射到 upload 路径谁拿到 URL 都能下载。这会带来两个问题未登录也能下载绕过权限下载次数统计失效管理员看不到热门资源。推荐用 Spring MVC 的ResponseEntityFileSystemResource做接口控制GetMapping(/api/resource/download/{id}) public ResponseEntityorg.springframework.core.io.Resource download(PathVariable Integer id, HttpServletRequest request) { // 1. 登录校验 User loginUser (User) request.getSession().getAttribute(loginUser); if (loginUser null) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } // 2. 只允许下载审核通过的资源 ResourceInfo info resourceService.getById(id); if (info null || info.getStatus() ! 1) { return ResponseEntity.notFound().build(); } // 3. 拼出实际文件路径 File file new File(uploadDir info.getFilePath()); if (!file.exists()) { return ResponseEntity.notFound().build(); } // 4. 记录下载日志并增加下载次数 downloadRecordService.save(loginUser.getId(), id); resourceService.increaseDownloadCount(id); // 5. 返回文件流中文文件名用 URLEncoder 处理 String encodedName URLEncoder.encode(info.getTitle() . info.getFileType(), StandardCharsets.UTF_8) .replace(, %20); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, attachment; filename*UTF-8 encodedName) .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(new FileSystemResource(file)); }这里每一步都有讲究。info.getStatus() ! 1把“未审核的资源不可下载”拦在业务层即使有人绕过前端按钮也拿不到文件。URLEncoder.encode解决中文文件名变成乱码的问题老代码里直接拼filename容易出现只在 Chrome 正常、其他浏览器乱码的现象。下载记录表每下载一次插一条数据一段时间后可以统计出“下载最多的资源 Top10”这就是答辩时能讲的运营价值。要小心一种情况前端如果走 Vite 代理下载接口返回的Content-Disposition里如果带中文Axios 的responseType: blob不会自动识别文件名需要后端额外把文件名字段放进响应头。我一般会在 header 里加一个自定义字段X-File-Name前端读取后再拼下载链接。这个细节源码里不一定做你可以作为二次开发补上。4.3 资源审核状态机上传、待审、通过、驳回的管理闭环没有审核的资源系统等于把网站内容安全交给了运气。比较完整的审核状态流是用户上传 - status0 待审核 管理员审核通过 - status1 已发布 管理员审核驳回 - status2 已驳回 reject_reason 填写原因 用户修改后重新提交 - status0 待审核状态只有三个数字但管理后台的查询逻辑发生了变化。普通用户端只查status1管理后台可以按状态筛选待审核列表是管理员打开后台之后第一个要看的页面。后端更新状态的方法非常简单PostMapping(/api/admin/resource/review) public Result review(Integer id, Integer status, String rejectReason) { if (status ! 1 status ! 2) { return Result.error(非法状态); } ResourceInfo info resourceService.getById(id); if (info null) { return Result.error(资源不存在); } if (status 2 StringUtils.isBlank(rejectReason)) { return Result.error(驳回必须填写原因); } info.setStatus(status); info.setRejectReason(rejectReason); resourceService.updateById(info); return Result.success(审核完成); }这里强制“驳回时必须有原因”是一个很小的校验但能让整个系统从“可用”变成“像样”。用户收到驳回后可以重新上传也可以修改资源描述后再提交。很多源码只做了“管理员能改状态”没有做“用户端我的上传里能看到驳回原因”这是最常见的缺漏。在演示时还有一条实战经验提前在数据库里插入 5 条status1的资源然后留 2 条待审核数据给现场走“审核”操作。这样既展示了列表页又演示了审核流程不会临时上传文件等半天。数据量不大但演示观感会好很多。5. 避坑与排查跑考研资源系统源码最容易翻车的5个位置5.1 node-sass 安装失败前端依赖装不上的真正原因现象执行npm install时终端报Error: Node Sass does not yet support your current environment或gyp: No Xcode or CLT version found安装进程卡在node-sass这个包上。前端页面一直起不来。原因很多 vue2 项目的 package.json 里依赖了 node-sass 4.x而 node-sass 需要下载与 Node 版本对应的二进制文件。本机 Node 版本一旦高于 Node 16或者新版本系统缺少 Python/C 编译工具就会安装失败。这不是你的代码有问题是年份和版本错配。解决不要硬装先用node -v查看版本然后用 nvm 切到 Node 14 或 16删除node_modules和package-lock.json重新执行npm install。如果不想切 Node可在 package.json 里把node-sass换成sass但需要同步改vue/cli-service的兼容配置风险更大。我建议用 nvm 切版本这是血泪经验里最省事的方案。5.2 数据源报错MySQL 时区、驱动版本与连接串玄学现象后端启动时日志出现The server time zone value Öйú±ê׼ʱ¼ä is unrecognized或者Failed to determine suitable driver class甚至直接提示Access denied for user rootlocalhost。原因MySQL 8 默认时区是 America 系列的旧表示法而 Tomcat/JVM 的时区解释不同老源码还在用com.mysql.jdbc.Driver这个类从 MySQL Connector/J 8.0 开始已经被移到com.mysql.cj.jdbc.Driver。账号密码不对属于配置问题。解决先把连接串改成下面这种标准写法jdbc:mysql://localhost:3306/kaoyan_resource?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrueallowPublicKeyRetrievaltrue是 MySQL 8 里颇多新手踩坑的参数它解决 caching_sha2_password 认证方式下初次连接拿不到公钥的问题。驱动类确保是com.mysql.cj.jdbc.Driver。改完还不通就在 MySQL 里执行ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 你的密码;再重启后端。5.3 上传的文件找不到相对路径和部署路径不一致现象上传文件时提示成功网页上也能看到文件记录但点击下载时 404或者到服务器目录里找不见文件。登录容器查看/data/kaoyan/uploads下确实有文件但项目里访问不到。原因源码把文件写在了相对路径比如./uploads而 Java 进程的工作目录不同。用 IDE 启动时工作目录是项目根目录用java -jar启动时工作目录却是执行命令的那个目录。一旦换位置路径就漂移了。解决统一改为绝对路径配置。在 application.yml 里定义my-resource.upload-dir: /data/kaoyan/uploads所有文件操作都用这个变量拼接不要再写new File(uploads)。同时给 Spring Boot 加一个静态资源映射让/upload/**能直接访问对应磁盘目录Configuration public class WebResourceConfig implements WebMvcConfigurer { Value(${my-resource.upload-dir}) private String uploadDir; Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadDir /); } }路径最后一定要带/否则会映射到上一级目录这是另一条小坑。5.4 中文乱码与文件名冲突字符集和 UUID 一个都不能少现象资源标题显示为问号或乱码上传两个同名的真题.pdf后上传的把前一个覆盖了下载文件时浏览器弹出的名字是乱码。原因数据库表字符集不是 utf8mb4连接串没带characterEncodingutf8或者文件名直接用了用户原始文件名没有做唯一化处理。解决建库时统一用DEFAULT CHARSETutf8mb4连接串带上useUnicodetruecharacterEncodingutf8。文件保存时使用UUID.randomUUID()生成文件名数据库只存原始标题用于展示这样彻底杜绝重名冲突。下载响应头里用filename*UTF-8形式编码文件名而不是直接拼filename数学笔记.pdf。5.5 跨域拦截与端口占用本地联调的两个隐形坑现象前端页面打开了点登录或上传浏览器 F12 里报No Access-Control-Allow-Origin header is present或者后端启动时报Port 8080 was already in use。原因Vite 开发服务器默认端口 5173 访问后端 8080属于跨域请求后端没开 CORS或者自带的 CORS 配置只允许了某个具体域名。端口占用则通常是之前启动的后端进程没杀掉。解决先杀掉占用端口的进程。Linux/Mac 用lsof -i:8080找到 PID 再killWindows 用netstat -ano | findstr :8080。然后在后端写一个全局 CorsConfig 放行本地开发端口Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/api/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowCredentials(true) .maxAge(3600); } }如果不想碰后端也可以在 Vite 的vite.config.js里配置 proxy 把/api转发到 8080这样浏览器看到的请求是同源的完全没有 CORS。两种方式选一个即可不要同时开很多层代理否则排查时绕来绕去。6. 部署与二次开发把毕业设计变成真正能用的WEB资源站6.1 打包部署jar包 Nginx反代 一台低配服务器本地跑通只算热身真正的考验在部署。后端打包命令始终是那一条mvn clean package -DskipTests然后把target目录下生成的 jar 上传到服务器用nohup java -jar kaoyan-resource-1.0.0.jar app.log 21 启动。上传目录用独立磁盘路径MySQL 用云数据库前端构建后npm run build把生成的dist目录交给 Nginx 做静态托管。前端请求/api时通过proxy_pass转发到后端 8080就不需要在代码里写死 IP 和端口。很多同学想找免费的 web 项目托管服务来省服务器钱但考研资源系统带着 MySQL、文件上传、会话管理不是纯静态站点免费的静态托管根本放不下后端。一台最低配的 Linux 服务器足够演示和几十人同时使用数据库和文件目录记得每隔几天备份一次。本地局域网演示也可以但不能保证答辩当天网络稳定所以我建议至少提前把 jar 包和 sql 脚本都备份到 U 盘。6.2 二次开发方向搜索、预览、积分与Web安全加固如果你的精力有余可以在这个基础上做三个小而准的升级。第一把资源列表的关键字搜索从LIKE %xx%换成 MySQL 全文索引或直接在标题字段加索引考研资料数量上千条之后LIKE 查询会明显变慢。第二给 PDF 资源加在线预览用 pdf.js 或后端转图片预览这个功能很讨喜能让你和“只做增删改查”的同行拉开差距。第三完善积分体系上传资源获得积分下载扣除积分管理员可调节积分开关。这会增加至少两张表但也是最容易在答辩中讲深的功能。web 安全方面必须补三刀上传接口继续收紧后缀白名单并校验文件真实类型所有管理员接口增加角色校验不能只靠隐藏按钮对资源标题和描述做 HTML 过滤防止 XSS 注入。考研资源站的用户可信度不高公开运营前一定要做内容审核日志保留上传者 IP、时间、审核人记录这是最容易被忽略的合规点。6.3 验收检查清单按下这张表走一遍才算把源码吃透检查项操作预期结果用户注册注册新账号可登录、个人信息可改上传流程上传 PDF 测试文件出现“待审核”状态文件落盘成功审核流程管理员驳回一条、通过一条驳回有原因通过后前台可见下载控制未登录访问下载接口返回 401 或跳转登录分类筛选按一级/二级分类查询资源列表正确过滤数据统计查看后台下载排行下载次数随下载行为增长部署验证重启服务器后访问域名页面和文件访问都正常我第一次给师弟调这种源码时专卡在 node-sass 上折腾了整整一下午后来养成了习惯解压后先把版本和环境列清楚再动手启动。高分的“基于WEB”毕设不会自动让你高分能稳定复制、解释清边界、补上安全细节才是真本事。希望帮到你。本文还有配套的精品资源点击获取
返回列表