恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Java毕设实战:养老院管理系统架构设计与核心实现解析
首页
资讯中心
/
Java毕设实战:养老院管理系统架构设计与核心实现解析
Java毕设实战:养老院管理系统架构设计与核心实现解析
发布时间:2026/10/7 6:29:24
简介面向计算机及相关专业毕业设计场景一套基于Java的敬老院管理系统毕业设计资源包涵盖源码、数据库、论文与操作演示视频为开发者和学生提供一站式参考。系统围绕敬老院日常管理设计包含系统管理员与护工两类用户覆盖老人信息管理、床位分配、护工薪资、请假记录、事故记录等模块的增删改查可快速搭建可运行的养老机构管理后台。压缩包共15个文件大小约69.38MB除源代码zip外还包括sql数据库脚本、部署演示视频、功能讲解视频、毕业论文doc及毕业答辩PPT、中期检查表等文件类型贯穿编码、建库、部署和答辩全流程。目前已有748人学习下载适合需要完成毕业设计或课程项目的学生参考可通过视频掌握部署与操作结合源码和论文进行二次开发与论文撰写。1. 养老院管理系统这个Java毕设为什么值得你认真对待它每年到毕设季这种标题的压缩包都会被反复下载。它承诺的不只是一段能跑的代码而是一套“源码视频数据库论文”的完整交付物。敬老院管理系统本质上就是一个标准的管理信息系统用Java把老人档案、床位分配、护理记录、费用收缴这几条业务线管起来替代手工台账和Excel表格。系统本身并不复杂但胜在业务完整、技术栈经典所以成了Java Web入门和毕业设计里被复现最多的项目之一。适合两类人一类是急着交毕设或课程设计的学生另一类是想要一套真实业务来打通Java后端三层架构的自学者。2. 架构与技术选型先搞清这套系统的技术栈再动手2.1 拆业务模块先有需求边界才有技术选型我不建议拿到压缩包就直接去跑代码。先看它的功能列表确认边界。绝大多数敬老院管理系统的模块划分是长这样的登录认证管理员、护理员、财务三种角色、老人档案管理基本信息、家属联系人、健康状态、房间床位管理楼栋—房间—床位三级结构、入住退住办理办入住、换床、退住结算、护理记录每日护理、用药提醒、费用管理床位费、护理费、伙食费收缴记录。为什么先拆模块因为这决定了数据库要建几张表、Controller要写多少个接口也决定了你后面改需求时动哪里。这正好是Java面向对象编程的设计思路先抽象对象再落库再写操作逻辑。如果你一上来就盯着代码看很容易被琐碎的增删改查淹没看不到业务的骨架。对于这个系统的业务量级用单体的三层架构就足够了不需要微服务、不需要Redis缓存硬上反而会拖慢你理解业务的进度。这一点在论文的“可行性分析”章节里也站得住脚技术选型匹配业务复杂度本身就是设计能力。2.2 拿到源码后先确认它是SSM还是Spring Boot标题里只写了“基于Java”这没说到关键点上。同一套业务的Java实现市面上既有SSMSpring Spring MVC MyBatis的老项目也有Spring Boot MyBatis的新项目两种都叫“基于Java”。怎么快速区分我一般看三个地方。第一看pom.xml的parent节点如果引用的是spring-boot-starter-parent就是Spring Boot如果没有parent只有一堆spring-webmvc、mybatis-spring坐标就是SSM。第二看配置文件名Spring Boot是application.properties或application.ymlSSM是applicationContext.xml加spring-mvc.xml。第三看启动方式有没有一个带SpringBootApplication注解的XxxApplication类。我把两种技术栈的差异整理成一张表方便你拿到压缩包后对号入座对比项SSM老项目Spring Boot项目配置文件applicationContext.xml spring-mvc.xml配置分散在多个XMLapplication.yml或application.properties集中管理启动方式打成war包丢进Tomcat的webapps目录内嵌Tomcat直接java -jar或右键main方法静态资源放webapp/static需要手动配置资源映射放src/main/resources/static开箱即用依赖管理坐标多且版本要自己对齐parent统一管理版本坐标明显减少适合人群想理解Spring老式XML装配的人想尽快跑通并用于毕业设计/面试讲解的人我自己的习惯是如果拿到的是SSM老包且你只是想交作业优先按SSM原样跑通不要中途换框架如果你要拿这套系统去面试讲项目建议花两周迁到Spring Boot因为现在Java开发工程师面试题里问Spring Boot的频率远高于SSM你讲项目时用Spring Boot也更贴近当前岗位的主流需求。2.3 JDK、MySQL、Tomcat版本搭配先对齐再运行这类压缩包最容易翻车的不是代码是版本环境。我看过很多同学因为JDK版本不对Tomcat直接变成黑匣子日志里全是看不懂的字节码异常。给你一套我常用的、兼容性最好的搭配组件推荐版本说明JDK8老项目里大量jar对JDK 17不兼容尤其cglib和旧版TomcatMySQL5.7或8.05.7对老项目最省事8.0需换驱动类名见第5章Tomcat8.5或9.0不要上Tomcat 10javax.servlet会被替换成jakarta.servlet老代码直接编译不过Maven3.6.3对老仓库兼容性最好开发工具IDEA 2021及以上自带Maven与Git支持开箱即用数据库工具Navicat或DBeaver用来核对数据字典和执行SQL脚本注意一个关键点如果项目里用的是JSP那必须配外置Tomcat如果是前后端分离后面章节会讲改造方案Tomcat只是内嵌资源服务器二者的部署路径完全不一样。这一点决定了你能不能从“跑起来”走向“部署到服务器上给答辩老师演示”。2.4 数据库连接配置让MyBatis正确找到MySQL不管是SSM还是Spring Boot第一步都是先把数据库连上。Spring Boot的application.yml长这样server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/jinglao?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.jinglao.entity逻辑说明先把端口定为8080datasource节点告诉Spring Boot去哪找MySQL。mybatis.mapper-locations指向XML文件的位置type-aliases-package让实体类在XML里写resultType时不用带全限定类名。这套配置是这个项目的命门连不上数据库时九成问题出在url参数上。参数说明url里有三个参数值得记。useUnicodetruecharacterEncodingutf8防止存入的中文变成问号useSSLfalse本地开发关掉SSL握手否则MySQL 8会打印一堆警告甚至连接失败serverTimezoneAsia/ShanghaiMySQL 8对时区敏感不加会直接报时区错误。如果是老SSM项目上面内容对应在jdbc.properties里键名不同但参数完全一样。改完之后先用Navicat手工连接一次数据库确认账号密码没问题再去启动项目。这一步能隔离掉很多“代码看起来没问题但就是连不上”的玄学问题。3. 数据库设计敬老院业务的核心是“人、床、护理、费用”四条线3.1 表结构拆解八张核心表四条业务线整个敬老院系统本质上就管理四件事人、床位、护理、费用。对应到数据库里八张核心表就能把这四条线完全撑起来。人线有三张表user登录用户也是员工、old_person老人、family家属。有的系统会把家属的联系方式直接塞进old_person表里省掉family这样做不是不行但老人有多个子女时数据就冗余了家属信息改动还要去改老人表耦合严重。床位线有三张表room房间、bed床位、check_in入住记录。注意room和bed分开建不要只用bed.room_no字符串表示房间否则统计“哪个房间住了几个人”时要靠字符串截取这是典型的低质量设计。护理线和费用线各一张核心表nursing_record护理记录和pay_record缴费记录。再加上一张可选的health_record健康档案用于存放体检和用药信息这套系统的库表设计就完整了。3.2 老人和床位为什么要用check_in表解耦这是整个表设计里最关键的决策点也是论文里最好写的设计亮点。新手最容易犯的错误是在old_person表里加一个bed_id字段表示老人当前睡哪张床。看起来简单但遇到换床就麻烦老人从301搬到302你得UPDATE old_person而且历史记录丢了当初谁住过这张床完全查不到。如果哪天要统计床位周转率你得靠日志或者翻台账数据库里没有痕迹。正确做法是引入check_in入住关系表。一个老人可以有多条入住记录每条入住记录指向一张床和一个时间段。同一时间段内一张床不能分配给两个人——这个约束在Service层校验而不单纯靠数据库。这种设计在表关系上就是old_person与bed之间的多对多通过check_in解耦成一对多。这也是“面向对象”思想落到关系数据库的经典例子对象之间有复杂的关联关系不该用加外键字段的方式硬塞而是抽出一张关系表来承载生命周期。答辩时老师如果问“你的数据冗余在哪里、重复入住怎么处理”这段话可以直接用。3.3 核心建表SQL给出一份可直接执行的DDL下面是这套系统里老人类、床位表、入住表的核心DDL。表名和字段名我都刻意避开了MySQL关键字你照抄或者照着改都行。CREATE TABLE old_person ( id INT PRIMARY KEY AUTO_INCREMENT COMMENT 老人ID, name VARCHAR(50) NOT NULL COMMENT 姓名, gender TINYINT NOT NULL DEFAULT 1 COMMENT 性别 1男 2女, id_card VARCHAR(18) UNIQUE COMMENT 身份证号, phone VARCHAR(20) COMMENT 联系电话, health_status VARCHAR(200) COMMENT 健康状况描述, create_time DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 建档时间 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT老人信息表; CREATE TABLE bed ( id INT PRIMARY KEY AUTO_INCREMENT, room_no VARCHAR(20) NOT NULL COMMENT 房间号如A-301, bed_no VARCHAR(20) NOT NULL COMMENT 床位号, status TINYINT NOT NULL DEFAULT 0 COMMENT 0空闲 1占用, UNIQUE KEY uk_room_bed (room_no, bed_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT床位表; CREATE TABLE check_in ( id INT PRIMARY KEY AUTO_INCREMENT, old_person_id INT NOT NULL COMMENT 老人ID, bed_id INT NOT NULL COMMENT 床位ID, check_in_time DATETIME NOT NULL COMMENT 入住时间, check_out_time DATETIME DEFAULT NULL COMMENT 退住时间NULL表示在住, charge_type TINYINT DEFAULT 1 COMMENT 1自理 2半护理 3全护理, KEY idx_person (old_person_id), KEY idx_bed (bed_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT入住记录表;逻辑说明old_person用utf8mb4是因为要存生僻字和特殊符号身份证号加UNIQUE约束防止重复建档。bed表里room_no和bed_no组合唯一保证同一房间内床位号不重复。check_in的核心是check_out_time设为NULL表示在住这样查“当前哪些老人住在哪张床”就变成一条WHERE check_out_time IS NULL语句非常高效。参数说明VARCHAR(18)对应二代身份证的18位TINYINT存性别和状态比枚举和INT更省空间DATETIME默认值用CURRENT_TIMESTAMP插入时就不用手动填时间。charge_type这个字段很关键它决定老人的收费标准费用模块要根据它来计算每月应收。3.4 字段类型、索引与建表后的修改我见过大量这种项目的建表SQL有几个通病帮你提前排掉。金额不用FLOAT或DOUBLE用DECIMAL(10,2)浮点算钱会精度出错这是财务模块的底线。性别不用VARCHAR存“男”“女”用TINYINT加注释展示层再翻译这也是后端开发规范。状态字段不要用NULL表示“否”用0和1NULL在统计COUNT时会漏数据逻辑判断也容易出bug。外键约束可加可不加但索引一定要加。身份证号、床位状态、入住时间这几个字段的查询频率极高不加索引到数据量上万时会明显卡顿。如果你的老人在500人左右的规模可能感受不到差别但论文里写“针对高频查询字段建立索引”是实打实的设计点。如果拿到别人的建表脚本想改结构用ALTER TABLE比如我给老人表加一个紧急联系人字段给入住表加一个入住时间索引ALTER TABLE old_person ADD COLUMN emergency_contact VARCHAR(50) COMMENT 紧急联系人; ALTER TABLE check_in ADD INDEX idx_in_time (check_in_time);这种“mysql数据库修改结构”的操作在调整数据字典的时候几乎每天都要做。但有一个坑必须提醒你改完数据库一定要同步更新实体类和Mapper的ResultMap否则MyBatis查出来的字段全是NULL而且是那种不报错、纯靠肉眼对比才能发现的诡异问题。4. 核心功能实现登录、档案、入住三条代码链路4.1 登录与权限拦截器比注解更适合这类单体系统登录是老生常谈但实现方式的选择有讲究。Spring Boot项目里最常用的有三种做法拦截器HandlerInterceptor、过滤器Filter、注解加AOP。对于这种角色少、页面多的单体系统我一般选拦截器理由很实际配置简单路径匹配直观而且面试被问“登录拦截怎么实现”时HandlerInterceptor是标准答案。先写一个登录接口RestController RequestMapping(/api/user) public class LoginController { PostMapping(/login) public Result login(String username, String password, HttpSession session) { // 实际项目里密码要加盐哈希这里为了演示判断逻辑简化 User user userService.findByUsernameAndPassword(username, password); if (user null) { return Result.error(用户名或密码错误); } session.setAttribute(loginUser, user); return Result.success(user); } }再写一个拦截器public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session request.getSession(); User user (User) session.getAttribute(loginUser); if (user null) { // 未登录跳转到登录页而不是返回JSON response.sendRedirect(/login.html); return false; } return true; } }逻辑说明Result是一个通用返回体success和error两个静态工厂方法分别返回成功和失败消息。登录成功后把User对象放进Session拦截器从Session里取取不到就重定向到登录页起到保护所有页面的作用。注册拦截器时需要放行登录接口和静态资源路径否则会出现“自己都进不去”的死循环。参数说明sendRedirect是重定向浏览器地址栏会变成登录页地址。如果你用response.setStatus(401)前端拿到的是无样式JSON对传统的JSP页面不友好。如果你想让不同角色看到不同菜单就在拦截器里再判断user.getRole()后再决定放行还是拒绝单靠登录拦截还不够但在这个体量下已经够用。4.2 老人档案的增删改查完整的三层架构写法老人档案是整个系统最基础的功能也是论文里“系统实现”章节的主体。我给出从Mapper到Controller的一整条链路这是任何Java管理系统的标准范式。先是实体类字段要和数据库一一对应不要多也不要少public class OldPerson { private Integer id; private String name; private Integer gender; private String idCard; private String phone; private String healthStatus; private LocalDateTime createTime; // getter/setter 略IDE生成即可 }Mapper接口只写方法签名public interface OldPersonMapper { int insert(OldPerson person); int updateById(OldPerson person); int deleteById(Integer id); ListOldPerson selectList(String keyword); }对应的XML里增删改查各一条SQL。给你看两个关键的insert idinsert parameterTypecom.jinglao.entity.OldPerson useGeneratedKeystrue keyPropertyid INSERT INTO old_person (name, gender, id_card, phone, health_status) VALUES (#{name}, #{gender}, #{idCard}, #{phone}, #{healthStatus}) /insert select idselectList resultTypecom.jinglao.entity.OldPerson SELECT * FROM old_person where if testkeyword ! null and keyword ! name LIKE CONCAT(%, #{keyword}, %) /if /where ORDER BY create_time DESC /select逻辑说明useGeneratedKeys让数据库自增主键回填到实体的id字段插入后立刻getId()就能拿到新纪录的ID后续做关联操作时特别有用。select里的where标签是MyBatis动态SQL条件为空时整段被去掉keyword只做模糊搜索搜索条件是动态拼出来的。参数说明LIKE的CONCAT写法能防止SQL注入不要直接传“%”加keyword加“%”拼接。ORDER BY create_time DESC让新建档的排前面管理端体验好。如果你要把关键字改成同时匹配姓名、身份证号、手机号就在if标签里多加两个OR条件查出来的结果集更实用。Service层再做业务校验比如身份证号不能重复、姓名不能为空然后调用Mapper。Controller只管接收参数、调Service、返回Result。这一套写下来你就把Spring容器里常说的“依赖注入”“组件职责”这些概念对上了Controller依赖ServiceService依赖Mapper全部交给Spring管理。4.3 入住办理为什么必须加事务入住不是一个insert就能完事的事。一次入住动作在业务上要完成三件事把床位状态改为占用、插入一条check_in入住记录、给该老人生成初始护理计划。这三件事要么全成功要么全失败。Java里用Transactional解决。我习惯加到Service实现类上而不是Controller因为事务边界属于业务逻辑不属于接口层。这里的关键点是换床、退住、费用结算这些动作都要同样处理。Service public class CheckInService { Transactional(rollbackFor Exception.class) public void checkIn(CheckInDTO dto) { // 1.查床位是否空闲 Bed bed bedMapper.selectById(dto.getBedId()); if (bed null || bed.getStatus() 1) { throw new BizException(床位不存在或已被占用); } // 2.床位改为占用 bed.setStatus(1); bedMapper.updateById(bed); // 3.写入住记录 CheckIn checkIn new CheckIn(); checkIn.setOldPersonId(dto.getOldPersonId()); checkIn.setBedId(dto.getBedId()); checkIn.setCheckInTime(LocalDateTime.now()); checkInMapper.insert(checkIn); // 4.初始化护理计划对应nursing_record表 nursingMapper.initPlan(dto.getOldPersonId()); } }逻辑说明第一步先查再改是为了避免把已占用的床位再分给别人这是并发控制的第一道防线。第2到第4步在同一个事务内任何一个抛异常数据库都会回滚床位不会被莫名占用入住记录也不会出现“只有一半”的脏数据。参数说明rollbackForException.class的意思是所有异常都触发回滚包括运行时异常和受检异常。如果你只写Transactional不写rollbackFor默认只在RuntimeException下回滚受检异常比如文件找不到就不会回滚这是很多“数据被写坏”的隐藏原因。这里要提醒普通业务系统里不建议在事务里做耗时操作比如发短信、调远程接口事务要短平快。宿管系统如果有定时任务给老人推送用药提醒那就单独拆一套流程别塞进checkIn事务里否则一个慢接口能把整个数据库连接池拖垮。5. 部署与避坑把这套Java系统跑起来的五个常见问题这一章是全文性价比最高的一章全是帮别人跑这类Java毕设项目时踩过的坑。每个问题都按“现象-原因-解决”写你按顺序排查能省下至少一个下午。5.1 MySQL 8的驱动类名和url参数现象项目启动后报java.lang.ClassNotFoundException: com.mysql.jdbc.Driver或者是Communications link failure。原因老项目里的驱动是mysql-connector-java 5.x类名是com.mysql.jdbc.DriverMySQL 8的驱动类名改成了com.mysql.cj.jdbc.Driver。如果你本地装的是MySQL 8却用旧驱动连不上是必然的。另一个常见原因是url里缺serverTimezoneMySQL 8对时区敏感直接抛异常。解决驱动坐标升级到8.0.xdriver-class-name改成com.mysql.cj.jdbc.Driverurl加上serverTimezoneAsia/Shanghai。第2.4节里的yml配置直接抄即可。Maven坐标从mysql:mysql-connector-java改成com.mysql:mysql-connector-j版本用8.0.33这类稳定版。提示如果你必须用老驱动连新数据库也不是完全不行但要在连接参数里额外处理SSL和时区出了问题排查成本极高不如直接升级依赖。5.2 页面中文乱码三层都要查现象页面显示的中文全是问号或者数据库里存进去是好的、查出来却在页面上变乱码。原因乱码是编码链路上某一层断了。JSP页面本身不是UTF-8、Spring的CharacterEncodingFilter没配、JDBC url没有characterEncodingutf8、MySQL表不是utf8mb4四层里有任何一层不对就乱。解决依次检查四个地方。JSP页面顶部的charsetSpring Boot里用配置类注册CharacterEncodingFilter或用server.servlet.encoding配置项数据库url里带characterEncodingutf8建表语句里的CHARSET设为utf8mb4。任何一层都不能漏。我之前遇到过最隐蔽的Tomcat的server.xml里Connector没加URIEncodingUTF-8页面表单GET提交的中文全乱怎么查都觉得代码没问题。修复后重启Tomcat、清浏览器缓存再验证一次。乱码问题一旦出现就是全站性的优先排查环境配置不要先怀疑业务代码。5.3 字段名踩了MySQL关键字现象执行INSERT或SELECT报You have an error in your SQL syntax反复检查SQL都觉得写得很对。原因字段名或表名命中了MySQL关键字比如desc、order、group、condition、rank。这类系统里最常踩的雷是描述字段叫desc排序字段叫order这些恰好是SQL关键字。解决优先改名desc改成descriptionorder改成sort_order一劳永逸。改不了时用反引号把字段名包起来但反引号会降低SQL可读性而且换了一个数据库方言就失效。更推荐直接改数据库字段不要留雷给后人踩。提示同一套系统里建表SQL建议开局就避开全部关键字。否则论文里的数据字典和实际数据库对不上时整改成本很高既要改SQL又要改XML又要改实体类。5.4 Tomcat启动成功但页面404静态资源全丢现象Tomcat启动没报错首页能打开但CSS、JS、图片全部404页面跟没穿衣服一样。原因SSM项目和Spring Boot对静态资源的默认路径约定不一样。SSM习惯把静态资源放webapp/static由DefaultServlet处理。如果Spring MVC配置里把DispatcherServlet映射到/又没有加资源映射静态资源就被拦截了。解决Spring Boot项目把静态资源放src/main/resources/static、public或resources下三选一即可。SSM项目在spring-mvc.xml里加一行mvc:resources mapping/static/** location/static//逻辑说明mapping指定浏览器访问时的URL前缀location指定实际文件目录。这样浏览器请求/static/css/style.css时Spring MVC不会把它当成Controller路径而是直接去webapp/static/css/下找文件。换成Spring Boot后这个配置内置了但偶尔会有新版IDE把资源放错目录的情况优先检查resources根目录。这类问题不报错纯靠肉眼排查是典型的“黑匣子”排错体验。一个实用技巧是打开浏览器F12看Network面板里失败请求的URL路径对比实际文件目录就能快速定位。5.5 LocalDateTime返回JSON报错现象接口返回的数据里createTime字段直接报错或者格式变成一串数字。原因Java 8的LocalDateTime不是java.util.Date老版Jackson默认不支持序列化需要jsr310模块。很多这种毕业设计项目的依赖恰好没加。解决加jackson-datatype-jsr310依赖版本跟着Spring Boot的parent走不用手写版本号。然后对时间字段统一配置格式实体类上可以加JsonFormat(pattern yyyy-MM-dd HH:mm:ss)接口返回给前端的就是可读的字符串。提示数据库层面尽量用DATETIME存时间不要用TIMESTAMP。TIMESTAMP的范围只到2038年DATETIME的范围大得多而且DATETIME不受时区影响做报表统计时更安全。这也是在设计论文数据字典时容易被追问的点。6. 答辩前的验证与进阶把“设计”讲成加分项这一章不谈功能谈怎么让这套系统在答辩时立住。评审老师最反感的是“能跑但说不清为什么这样设计”反过来能把设计理由讲明白的即使代码有小瑕疵也比纯会跑分高。先给出一张我用过的功能验证清单答辩前一晚按清单把每个动作亲手点一遍能挡住大多数演示翻车模块操作预期结果登录输入错误密码页面提示用户名或密码错误不进入主界面档案新增老人身份证重复系统拒绝入库并提示身份证已存在入住选择占用中的床位提示床位不可用数据不被写入退住办理退住结算床位状态变空闲check_out_time写入护理为未入住老人添加记录系统提示先办理入住统计费用汇总与逐条缴费明细对账一致再加一个让代码显得有分量的分页技巧。很多这个体量的系统一次性把全部数据查出来20条数据没问题500条就卡。用MyBatis的PageHelper分页三行代码解决PageHelper.startPage(pageNum, pageSize); ListOldPerson list oldPersonMapper.selectList(keyword); PageInfoOldPerson pageInfo new PageInfo(list);逻辑说明PageHelper是MyBatis的分页插件startPage传入页码和每页条数插件会自动拦截下一条SQL并拼接LIMIT语句。PageInfo里封装了总条数、总页数、当前页数据列表前端渲染分页栏时直接取这些字段。参数说明pageNum从1开始pageSize设为10或20比较合适。如果接口还要求返回总条数用于前端显示“共xx条”PageInfo.getTotal()直接取。如果还有时间可以把JSP换成Vue做前后端分离。后端接口不用大改只是把返回JSON的Controller保留前端用Vue脚手架搭一个管理界面通过接口对接。这个改造在面试讲项目时可以当亮点“我做的是Java后端前端用Vue通过Restful接口对接。”这句话在Java开发工程师面试里的说服力比“我会JSP”高不少。最后说点我自己的教训。我最早写这类系统时恨不得把报表、权限、定时任务全堆进去结果bug全出在那些“炫技”的地方。后来我把重心改成把入住和退住的事务边界、索引设计、参数校验这些基本功做到位反而答辩时每个问题都能接得住。管理系统拼的从来不是技术新而是边界清楚、数据经得起追问。希望帮到你。本文还有配套的精品资源点击获取