首页 / 资讯中心 / 文章详情

基于SSM的医院体检管理系统毕设资源解析:JWT登录与权限控制

基于SSM的医院体检管理系统毕设资源解析:JWT登录与权限控制 ★ FEATURED ARTICLE
简介基于SSM框架的医院体检管理系统完整毕业设计项目面向计算机专业学生与Java Web学习者可满足毕业设计、课程设计或期末大作业需求。系统涵盖体检套餐管理、预约登记、项目检查、报告录入等核心业务采用Spring、SpringMVC、MyBatis整合架构配合Vue前端实现前后端分离开发。代码完整且可运行配有SQL数据库脚本和启动脚本经导师指导评审获高分适合直接作为项目模板或实战练手素材也可快速修改用于其他管理类系统。压缩包共855个文件大小仅25.46MB文件类型涵盖Java源码、Vue组件、JavaScript逻辑、SQL数据库脚本、XML配置以及png/jpg图片素材、mp4演示视频等覆盖从后端逻辑到前端页面、从环境部署到运行演示的完整链路。资源附数据库结构说明、部署文档和操作视频可帮助快速搭建环境并理解SSM项目开发流程。已有101人学习下载适合需要参考真实完整项目的学生是毕业设计答辩与SSM实战入门的高性价比资料。1. 基于SSM的医院体检管理系统这份毕设资源值不值得下先给个明确结论如果你正在用 Java 做毕业设计或课程设计且选题范围锁定在 Web 管理系统这套基于 SSM 的医院体检管理系统属于典型拿来就能跑、改改就能交的资源。项目采用 Spring SpringMVC MyBatis 组合前端保留了传统 JSP 页面另外带了一套 Vue 改造版页面两者通过同一套后端接口联动。资源里包含完整源码和数据库脚本启动入口做成三个 bat 文件1-install.bat 装依赖、2-run.bat 起服务、3-build.bat 打包基本把从零到运行的过程压成了三下双击。对导师催进度、自己还没把 SSM 串明白的计算机专业学生来说这套代码的价值不在于功能有多炫而在于它把登录鉴权、角色权限、体检订单流转、检查项管理这些毕设高频模块都串好了能让你把省下来的时间花在论文和答辩 PPT 上。全文我会按源码结构、启动流程、登录链路、数据库设计、踩坑记录、二次开发顺序拆完读完你不仅知道它怎么跑起来还知道改哪里能变成你自己的东西。2. 项目结构与启动链路从源码目录到本地跑起来拿到资源压缩包先别急着双击任何 bat 文件。先花五分钟把目录结构看一遍搞清楚每个文件是干什么的后面排错能少走一半弯路。2.1 从残留的 .bak 文件反推项目改造轨迹解压后你会看到一批.bak后缀文件比如main.css.bak、update-password.vue.bak、IndexAsideStatic.vue.bak。这些不是垃圾文件也不是打包失误它们是上一轮开发者修改前端时留下的备份。.bak的存在本身说明两件事这个项目经历过从纯 JSP 到 JSP Vue 混合的改造过程改造不是一次推翻重来而是直接在原文件上改完备份一份。对我这类习惯改前先备份的人来说看到.bak文件反而觉得踏实。具体到功能归属update-password.vue.bak对应 Vue 端的修改密码页面说明前端菜单里个人中心 修改密码这个入口是后补的IndexAsideStatic.vue.bak对应左侧菜单栏组件带 Static 后缀意味着这个版本的菜单是静态写死配置的不是从后端接口动态加载的BreadCrumbs.vue.bak和IndexHeader.vue.bak分别是面包屑导航和顶部栏组件这两个是管理后台的通用骨架部分。我说一下这套结构里最常见的启动失败原因JDK 版本不匹配。.classpath文件和.project文件是 Eclipse 的项目描述文件里面记录了项目依赖的 JRE 版本。如果文件里写的是 JDK 1.8而你机器装的是 JDK 11 甚至 17MyEclipse 或 Eclipse 导入项目后会直接报Unsupported major.minor version的编译错。解决方式不是换 JDK而是右键项目 Properties Java Build Path 修改 JRE System Library 为你本机版本再看 Compiler 级别是否对齐。2.2 三个批处理脚本先懂再跑资源根目录下有1-install.bat、2-run.bat、3-build.bat三个脚本。很多人拿到手就双击结果1-install.bat窗口一闪而过什么也没发生。这不是脚本坏了而是 bat 脚本里的 Maven 命令可能因为本地仓库路径、镜像源或 JDK 环境变量的问题静默失败了。建议你先用文本编辑器打开这些脚本看里面的具体命令。一个典型的1-install.bat内容大致如下mvn clean install -DskipTests echo install done! pause逻辑很简单先清理旧编译产物再执行 Maven 打包并跳过单元测试最后暂停等待用户按键。pause的作用是让窗口停在屏幕上方便你截图看报错信息。如果双击窗口仍然闪退说明mvn命令没有被系统识别也就是 MAVEN_HOME 环境变量没配置或者 Maven 版本过老。我一般建议在命令行手动执行一次mvn -v这一步能同时验证两件事Maven 是否安装成功、当前生效的 JDK 是哪个版本。如果mvn -v输出的 Java version 和你预期不一致大概率是JAVA_HOME指到了别的 JDK 安装目录。这种问题改脚本是没用的去系统环境变量里把JAVA_HOME指正即可。2-run.bat通常是启动 Tomcat 的命令常见内容无非是mvn tomcat7:run注意这里用的是tomcat7插件不是 Spring Boot 那种内嵌容器。也就是说这个项目是一个传统 war 包项目最终部署目标是外部 Servlet 容器。用tomcat7:run启动时项目不会打包成 war 文件而是直接把当前工程挂到插件内置的 Tomcat 7 容器上运行。这对大部分毕设场景够用了但有一个隐患如果你本机装了独立的 Tomcat 9并且和这个项目里的 Servlet API 版本有冲突运行期会抛NoSuchMethodError之类的问题。3-build.bat对应打包操作mvn package -DskipTests执行完后target目录下会生成 war 包把这个 war 丢到独立 Tomcat 的webapps目录就能外部部署。这块我要强调一个细节mvn package默认不打进源码和资源文件之外的依赖依赖全部从 Maven 中央仓库拉取。如果有些依赖在国内网络环境下拉取超时建议在pom.xml所在的目录下建一个settings.xml配好阿里云镜像源再跑脚本。2.3 导入 Eclipse / MyEclipse 的具体步骤这套项目用的是 Eclipse 系列 IDE 的标准工程结构不是 IDEA 的 Gradle 工程。如果你日常用的是 IntelliJ IDEA导入方式要选File New Project from Existing Sources然后选中pom.xml让 IDEA 按 Maven 模型重新索引。这里有一个 ID 和 Eclipse 行为不一致的地方IDEA 默认会自动下载依赖并建立索引Eclipse 需要右键项目 Maven Update Project 才会强制刷新依赖。我建议的操作顺序是mvn clean install -DskipTests确认本地仓库已经拉齐依赖后再打开 IDE 导入工程。这个顺序能避免 IDE 里一片红色报错却分不清是代码问题还是依赖没拉下来的问题。常见做法是先命令行验证编译通过再导入 IDE。2.4 启动后页面长什么样默认端口是 8080Tomcat 插件配置的 context path 一般在 pom.xml 里写死。启动完成后浏览器访问的是http://localhost:8080/项目名/login.jsp登录页属于传统 JSP 页面用户体系分为管理员、医生、用户三种角色对应的路由跳转逻辑会在后面讲 JWT 登录时展开。到这里项目已经能跑起来了。但如果你在启动阶段就遇到各种报错别急我后面有一整章专门讲避坑先把当前这条链路走通再往下看。3. JWT 登录与权限控制从表设计到拦截器校验SSM 项目最常见的登录方案无非三种Session 会话保持、Shiro 安全框架、JWT 令牌。这个项目用的是 JWT这一点在数据结构上体现得很明显也恰恰是它能从传统 JSP 页面平滑过渡到 Vue 改造版页面的原因。你可以理解为后端签发一个加密令牌给前端前端每次请求把令牌带在 Header 里后端拦截器校验令牌合法性不用在服务端存登录状态。3.1 用户表与角色字段的设计逻辑登录模块相关的核心表是用户表我按常见字段结构还原一下具体字段名请以资源里的 SQL 脚本为准CREATE TABLE user ( id INT(11) NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL COMMENT 登录名, password VARCHAR(255) NOT NULL COMMENT 加密后的密码, role INT(11) NOT NULL COMMENT 角色1管理员 2医生 3用户, real_name VARCHAR(50) DEFAULT NULL COMMENT 真实姓名, phone VARCHAR(20) DEFAULT NULL COMMENT 手机号, status INT(11) DEFAULT 1 COMMENT 1启用 0禁用, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8mb4;这个表有几个值得注意的设计点。password字段存储的不是纯文本而是某种加密后的密文常见的做法是 MD5 加盐或 BCrypt。如果是 MD5 加盐盐值通常会拼接在密码字段内部比如salt $ md5(salt password)的格式如果是 BCrypt密码本身就是一段带随机盐的哈希串前端传明文后端校验时用工具类比对。你拿到源码后第一件事应该去service层找到登录接口实现类看密码比对用的哪个工具类因为论文里的系统安全性分析部分要写这一段。role字段直接决定登录后的跳转目标。管理员进后台管理页医生进体检结果录入页普通用户进预约和个人报告页。如果不想引入 Spring Security 或 Shiro 这类重量级框架一个role字段配合前端路由判断就是最简单的权限控制方案。3.2 JWT 的生成与校验核心代码项目拦截器层通常叫JwtInterceptor或TokenInterceptor看一下核心方法public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 放行登录接口 if (request.getRequestURI().contains(/login)) { return true; } // 从请求头取 token常见 key 是 Authorization 或 token String token request.getHeader(Authorization); if (token null || token.isEmpty()) { response.getWriter().write({\code\:401,\msg\:\未登录\}); return false; } // 解析 token 并校验签名 try { Claims claims JwtUtil.parseJWT(token); request.setAttribute(userId, claims.get(userId)); request.setAttribute(role, claims.get(role)); return true; } catch (Exception e) { response.getWriter().write({\code\:401,\msg\:\token无效或已过期\}); return false; } }逻辑说明第一步放行/login路径否则登录接口自己都过不了拦截器会形成死循环第二步从请求头取 token这里有个前后端约定问题用 Vue 改造版页面时axios 拦截器里必须设置headers: {Authorization: Bearer token}大小写和前缀都要对齐JWT 工具解析时会去掉前缀第三步解析 token成功就把用户 ID 和角色塞进 request 上下文后续 Controller 直接RequestAttribute取。参数说明JwtUtil.parseJWT底层依赖io.jsonwebtoken库Claims对象里存的就是签发时放进 token 的自定义字段。token 的有效期在JwtUtil里会定义常见值是EXPIRE_TIME 1000 * 60 * 60 * 2也就是两小时。如果测试时频繁掉登录状态检查是不是这个过期时间设短了。3.3 登录接口的完整调用链Controller 层的登录接口大致流程是接收用户名和密码 → 调 Service 层查询用户 → 校验密码 → 签发 token → 返回给前端。伪代码如下PostMapping(/login) ResponseBody public Result login(RequestBody LoginForm form) { User user userService.findByUsername(form.getUsername()); if (user null) { return Result.error(用户不存在); } // 这里用加密工具类校验密码 boolean ok PasswordUtil.matches(form.getPassword(), user.getPassword()); if (!ok) { return Result.error(密码错误); } if (user.getStatus() 0) { return Result.error(账号已被禁用); } // 签发 token携带 userId 和 role String token JwtUtil.createToken(user.getId(), user.getRole(), user.getUsername()); return Result.success(token, user); }逻辑说明Result是统一返回体code200表示成功code500表示业务错误。前端拿到 token 后存入localStorage每次请求由 axios 拦截器自动附加。user.getRole()拿到的是 int 类型前端根据这个值渲染不同的菜单项这就实现了最基础的 RBAC 思路虽不完整但对付毕设答辩足够。关于PasswordUtil有一个坑要提醒如果数据库脚本里预置的种子账号密码和PasswordUtil的加密规则不一致你会遇到明明 SQL 里有这个账号登录却一直提示密码错误的怪事。排查方法很简单写一个临时测试类调用PasswordUtil加密一次看结果是否和数据库里的一致。不一致就说明 SQL 脚本里的种子密码是拿别的工具生成的需要手动更新。3.4 小程序 / 移动端的兼容性预判这套后端登录接口是纯 REST 风格返回 JSON。意味着如果答辩时导师要求做一个简单的移动端页面你可以不碰后端直接把登录请求打到这个接口上用wx.request或小程序原生请求库模拟。关键是把Content-Type: application/json设对参数按LoginForm的字段名传。4. 核心业务模块与数据库设计体检订单流转和数据表关系登录只是入口体检管理系统真正撑起论文篇幅的是业务数据流用户预约体检 → 管理员安排体检项目 → 医生录入各项指标 → 用户查看报告。这个流程对应到数据库就是一张主订单表配合多张子表的设计模式。4.1 预约订单表状态字段决定界面按钮订单相关的表通常叫health_order或appointment关键字段如下CREATE TABLE health_order ( id INT(11) NOT NULL AUTO_INCREMENT, order_no VARCHAR(32) NOT NULL COMMENT 订单编号生成策略时间戳随机数, user_id INT(11) NOT NULL COMMENT 预约用户, package_id INT(11) DEFAULT NULL COMMENT 体检套餐ID, status TINYINT(4) NOT NULL DEFAULT 0 COMMENT 0待确认 1已确认 2体检完成 3已取消, appointment_date DATETIME DEFAULT NULL COMMENT 预约体检时间, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这个status字段是整个订单模块最容易扩展也最容易出 bug 的地方。前端页面会根据 status 渲染不同操作按钮0显示取消预约按钮1显示确认报到和开始体检按钮2显示查看报告按钮。如果你在二次开发时新增了一个状态比如已退款不能只改数据库注释还要同步改前端 JSP 页面和 Vue 页面的状态判断逻辑否则会出现后端状态已经变了、前端按钮还是旧行为的情况。数据字典在毕设论文里可以单开一节写这是凑字数和加图的好素材。4.2 体检套餐与检查项表的冗余设计有一个常见的设计误区把套餐和检查项直接合并成一张表用逗号分隔存检查项 ID。这在毕设级别的系统里虽然能跑但答辩时很容易被导师追问第三范式你考虑了没有。合理的方案是三张表package套餐、check_item检查项、package_item_rel关联中间表。我在源码里也能看到类似的建表痕迹部分页面已经把套餐下的项目列表单独渲染成一列。关联表的字段设计可以参考:CREATE TABLE package_item_rel ( id INT(11) NOT NULL AUTO_INCREMENT, package_id INT(11) NOT NULL, item_id INT(11) NOT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;为什么不用中间表两个原因第一套餐和检查项是多对多关系中间表是标准解法第二后期如果要做按检查项统计体检人数的报表直接 join 中间表比解析逗号分隔的字符串快得多。SQL 查询的典型写法SELECT ci.item_name, COUNT(*) FROM package_item_rel pir LEFT JOIN check_item ci ON pir.item_id ci.id LEFT JOIN health_order ho ON ho.package_id pir.package_id GROUP BY ci.item_name;这段 SQL 的意思是通过关联表把套餐类型、检查项名称和订单表串起来再按检查项分组统计数量。这就是体检中心最基础的哪些项目检查人数最多统计报表。做这个功能可以在答辩时展示你对多表关联的掌握程度远比 CURD 加分。4.3 体检结果表医生的录入与用户报告查看体检结果表是整个系统中字段最复杂的一张表因为不同检查项的结果数据类型不一样。身高体重是数字血常规是字符串加单位B 超结论是一段文字描述。横向建表会爆炸所以通常的做法是拆成主表和明细表CREATE TABLE exam_report ( id INT(11) NOT NULL AUTO_INCREMENT, order_id INT(11) NOT NULL COMMENT 关联健康订单, doctor_id INT(11) NOT NULL COMMENT 录入医生, summary TEXT COMMENT 总检结论, advice TEXT COMMENT 健康建议, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;summary和advice字段用TEXT类型是因为内容长度不固定VARCHAR(255) 不够用。这里有一个容易被忽略的编码问题字段可以容纳 255 个字符但如果前端提交了一个包含表情符号的字符串数据库连接层没有设置characterEncodingutf8mb4emoji 会被存成乱码。常见的 MySQL 连接串应该写成jdbc:mysql://localhost:3306/health?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/ShanghaiserverTimezone参数在 MySQL 8.x 版本下必须加否则驱动会报时区错误。useSSLfalse则是为了避免开发环境下 SSL 握手警告。4.4 数据库脚本的使用细节拿到sql文件后不要直接用 Navicat 双击运行。我建议先在命令行里创建好 utf8mb4 编码的数据库再导入脚本CREATE DATABASE health_db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;然后执行source命令导入表结构和种子数据。这一套流程能避免 Navicat 图形界面导入时因客户端默认编码引发的中文乱码问题。种子数据里一般包含管理员的初始账号常见的默认密码是admin或123456以脚本里的 INSERT 语句为准。如果导入后发现中文全是问号重建数据库用命令行方式再试一遍九成是编码问题不是脚本问题。5. 毕设新手避坑四类高频问题与排查路径这一章是全文最杀时间的地方。我把在这个项目上最常见的四个坑按现象 → 原因 → 解决拆开写每条都能对应到你双击 bat 或启动 Tomcat 后看到的某个具体报错。5.1 报错一tomcat7:run 启动后页面 404现象控制台显示 Tomcat 启动成功浏览器访问http://localhost:8080/却是 404 或空白页。原因项目没有被挂载到根路径。tomcat7-maven-plugin默认的path是项目名也就是说你要访问的是http://localhost:8080/项目名/而不是根路径。另外还有一种更隐蔽的情况IDE 里没有把项目的 web 资源目录加入部署配置Tomcat 启动时根本没加载到 JSP 页面。解决先在 pom.xml 里看tomcat7-maven-plugin配置plugin groupIdorg.apache.tomcat.maven/groupId artifactIdtomcat7-maven-plugin/artifactId version2.2/version configuration port8080/port path//path /configuration /plugin如果path//path已经设置成根路径访问http://localhost:8080/login.jsp就是正确的。如果path没配访问地址就要带上 project name。以后每次启动前先看一眼控制台第一行日志Tomcat 会打印当前的 context path。5.2 报错二JDK 版本报 UnsupportedClassVersionError现象运行mvn clean install编译通过但启动时抛java.lang.UnsupportedClassVersionError后面跟着一串Class ... has been compiled by a more recent version of the Java Runtime。原因项目里有些依赖或编译产物是 JDK 11 编译的你运行时用的是 JDK 8或者反过来。Maven 编译时用的 JDK 版本和运行 Tomcat 的 JDK 版本不一致。解决统一 JDK 版本。检查顺序分三步。java -version mvn -version echo %JAVA_HOME%三步输出的 Java 版本如果不一致就说明 IDE / Maven / 系统环境变量各自指向了不同的 JDK。我习惯在项目的pom.xml里显式声明编译版本properties maven.compiler.source1.8/maven.compiler.source maven.compiler.target1.8/maven.compiler.target /properties这样 Maven 编译时会忽略系统默认 JDK 版本强制按 1.8 编译。注意1.8和8是等价的写法别纠结细节。5.3 报错三数据库连接 Access denied or Unknown database现象启动后第一次请求数据库相关的接口控制台抛Access denied for user rootlocalhost或Unknown database health_db。原因jdbc.properties或applicationContext.xml里的数据库账号、密码、库名和本地环境不一致。这类问题完全是环境配置导致和代码逻辑无关。解决打开jdbc.properties核对三项配置jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/health_db?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password123456提示com.mysql.jdbc.Driver是 MySQL 5.x 的驱动类名MySQL 8.x 驱动改成com.mysql.cj.jdbc.Driver。如果报错信息里提了Loading class com.mysql.jdbc.Driver相关的警告把驱动坐标从mysql-connector-java:5.1.x升到8.0.x并改掉 URL 里的参数。5.4 报错四前端页面样式加载失败或接口报 CORS 跨域现象用 Vue 改造版前端页面单独启动时页面能打开但接口请求全部失败控制台报跨域错误或者 JSP 页面打开后没有样式纯文本错乱。原因JSP 页面没样式通常是DispatcherServlet拦截了静态资源请求web.xml里加了/拦截规则但没放行.css、.js。Vue 页面跨域则是前端服务端口和后端 8080 不一致。解决先处理 JSP 静态资源放行在 SpringMVC 配置里加mvc:resources mapping/static/** location/static//然后处理 Vue 跨域。最简单的方案是在后端加一个全局 CORS 配置类Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOrigins(*) .allowedMethods(GET, POST, PUT, DELETE) .allowedHeaders(*); } }allowedOrigins(*)表示允许所有来源访问只适合开发调试部署上线时应该改成具体的前端域名。allowedMethods列出的方法要和前端 axios 实际使用的方法对上否则预检请求会失败。把这段配进去Vue 页面里调接口就不会再报跨域了。真实场景里遇到跨域问题先看请求头有没有Access-Control-Allow-Origin响应字段没有就是后端没配跨域不用去怀疑前端代码。6. 答辩加分的二次开发从菜单权限到体检报告导出代码能跑只是及格线答辩想要高分还得让导师看到你动了脑子改了代码的痕迹。我在大量毕设项目里发现一个规律被追问得最少的学生不是在答辩时口若悬河讲架构的而是当场演示了一个导师预期之外的细节功能。这一章给三个改动成本低、答辩效果好的切入方向。6.1 前端菜单按角色动态过滤原项目的IndexAsideStatic.vue静态菜单是写死的所有角色登录后看到的菜单一样。这不太合理因为普通用户不该看到用户管理和医生管理入口。改造方式是让登录接口把用户角色带回来前端根据角色过滤菜单数组。核心改动在router/index.js或侧边栏组件的数据初始化const allMenus [ { path: /dashboard, name: 首页, role: [1, 2, 3] }, { path: /user, name: 用户管理, role: [1] }, { path: /doctor, name: 医生管理, role: [1] }, { path: /order, name: 预约管理, role: [1, 2, 3] }, { path: /report, name: 体检报告, role: [2, 3] } ]; // 根据当前用户的角色过滤菜单 function filterMenus(role) { return allMenus.filter(m m.role.includes(String(role))); }逻辑说明allMenus里的role字段是字符串数组和登录接口返回的role做匹配决定最终渲染哪些菜单项。这个改动虽然简单但答辩时你可以说这是基于角色的访问控制是对原有静态菜单的增强比讲我封装了 axios更有区分度。6.2 体检报告导出与 Sheet 命名修正资源自带的前端页面里有一个体检报告下载入口但实际执行时可能因为 POI 库版本问题导出乱码。这里先说出问题现象导出文件能打开但 Sheet 名因为是中文到了 Excel 里变成Sheet1或者报文件名非法。原因通常是 POI 版本对新特性支持不完整。常见的导出逻辑代码放在 Service 层用 Apache POI 操作XSSFWorkbook。如果版本太老中文 Sheet 名会因编码格式问题被替换。修复方式是检查pom.xml中 POI 的版本至少要用 4.1 以上并且下载报告时前端 axios 要设置响应类型为 blobaxios.get(/report/export, { responseType: blob }).then(res { const blob new Blob([res.data]); const link document.createElement(a); link.href URL.createObjectURL(blob); link.download 体检报告.xlsx; link.click(); });逻辑说明responseType: blob是二进制流下载的关键缺了这一行导出来的文件大概率是乱码或损坏。link.download的xlsx后缀要和后端生成的文件格式一致否则 Excel 打开时提示格式不匹配。6.3 后端对体检报告导出的校验导出报告前后端一定要做权限校验。否则任何登录用户都能导出别人的体检报告这在答辩演示时是会被追问的安全漏洞。在 Controller 层加一个简单的判断GetMapping(/export/{orderId}) public void export(HttpServletResponse response, PathVariable Integer orderId, RequestAttribute Integer userId, RequestAttribute Integer role) { HealthOrder order orderService.getById(orderId); if (role ! 1 !order.getUserId().equals(userId)) { throw new BusinessException(无权导出该报告); } // ... 生成 Excel }这里的核心是RequestAttribute Integer userId从 JWT 拦截器塞进请求上下文里取当前登录人。role为 1 的管理员可以导出任意报告普通用户只能导出订单归属是自己的报告。这一行判断对论文里系统安全性设计的内容填充非常有用。6.4 收尾的习惯这套资源我前前后后拆过三遍每一次翻车都出在环境不一致上要么是 JDK 版本要么是数据库编码要么是前端静态资源被拦截。从那以后我每次拿到新毕设项目的第一件事不是打开代码读逻辑而是按看 pom.xml 依赖版本 → 看 jdbc.properties 连接串 → 看 web.xml 拦截规则这个顺序走一遍。三个文件看完这个项目能不能跑、哪里可能出问题心里基本有数。希望这个排查顺序也帮到你毕业设计这东西跑起来一次后面就顺了。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站