
计算机Java毕设实战基于Spring Boot的日报管理系统设计与实现每年毕设季我都能在后台收到一堆私信问日报管理系统怎么做Spring Boot毕设从哪下手。这个题目确实经典——它既不复杂到让新手崩溃又能把JavaWeb的核心知识点全部串起来工作量可控、答辩有得讲、代码量也够写满论文。这篇文章我就用实际做过的一个基于Spring Boot的日报管理系统项目把从需求分析、表结构设计、核心代码实现到部署上线的完整链路拆开讲清楚。项目用到的技术栈是Spring Boot MyBatis-Plus MySQL Thymeleaf附完整源码、部署说明和演示视频。之所以强调完整两个字是因为太多人卡在了半成品上登录做了一半、日报提交了没人审核、统计图表画不出来。做完一个能跑的、功能闭环的系统和做完一个只能看界面的Demo完全是两个层级。我会把每一步的思考过程、参数选择逻辑和踩坑记录都写出来你照着做甚至可以直接替换成自己的业务场景。1. 项目概述与选题思路1.1 为什么选日报管理系统日报管理系统的核心业务非常明确员工每天填写当天的工作内容、进度、明日计划主管或管理员进行查看、审阅和统计。这个业务场景几乎覆盖了JavaWeb开发的所有基础能力——用户的注册登录、角色的权限区分、数据的增删改查、时间维度的统计聚合、文件上传日报可能附带附件、权限拦截、异常处理等。从毕设的角度看这个选题有几个天然优势。第一业务需求容易调研每个同学的实习经历或者身边朋友的职场日常都能提供真实需求不需要编造复杂场景。第二功能边界清晰不会像电商系统那样陷入订单状态机、库存扣减、支付回调等无穷无尽的细节。第三演示效果直观日报列表、部门汇总、月度统计几张页面一展示评委立刻能理解系统在做什么。第三点其实是很多同学选题目最容易忽略的——答辩现场不是看你写了多少行代码而是看你能不能在五分钟内让评委看懂你的系统解决了一个什么问题。日报管理系统在这方面的优势是天然的界面放出来就是一张张日报卡片和一个统计面板任何一个不懂技术的人都能明白它在干嘛。1.2 技术选型的前因后果技术栈选择上我最终确定的是Spring Boot 2.7.x MyBatis-Plus 3.5.x MySQL 8.0 Thymeleaf Layui。这套组合在当年是JavaWeb毕设的标准答案放到现在依然完全够用甚至可以说非常稳妥。Spring Boot的选择没什么悬念它解决了传统SSHSpring Struts Hibernate配置繁琐的问题内嵌Tomcat、自动装配、约定大于配置一个main方法就能启动项目。对毕设来说你不需要理解Spring Boot底层自动装配的全部原理但答辩时至少能说清楚spring-boot-starter-web这个依赖干了什么——它帮我们自动配置了DispatcherServlet、内嵌Tomcat、JSON序列化等一堆Web开发必需组件。MyBatis-Plus相比原生MyBatis最大的价值是单表CRUD几乎不用写SQL。BaseMapper里内置了selectById、insert、updateById、selectPage这些方法日报表、用户表这些简单增删改查全都能直接调用。更贴心的是它自带分页插件用起来就是一页代码的事。后面我会在实现部分展示具体用法。Thymeleaf选择的原因很现实——Spring Boot官方推荐它就是它最大的理由。不过在实际开发中我后来把前端部分混用了Layui的组件库。Layui虽然官方已经停止维护但它的表格、表单、弹层组件在这类管理系统的开发效率上依然能打而且是纯浏览器端渲染不用去折腾Node.js构建链。对于毕设项目来说你不需要在Webpack和Vite的配置里浪费任何时间。数据库选MySQL 8.0是因为它现在已经是各大云服务器默认的版本了8.0的窗口函数在写统计SQL时非常好用。这里要提醒一句如果你的云服务器是宝塔面板安装的MySQL默认字符集可能是utf8mb4或latin1创建数据库时一定要显式指定utf8mb4不然后面存中文日报内容会出现乱码。2. 系统核心功能与数据库设计2.1 功能模块划分日报管理系统的核心模块我按角色拆分为三类视角来设计员工端、主管端、系统管理端。这个拆分方式直接决定了权限模型的复杂度。员工端的功能是登录、填写当日日报工作内容、完成进度、遇到的问题、明日计划、查看自己的历史日报、修改未审批的日报、查看个人日报统计连续打卡天数、本月提交次数。主管端在员工端的基础上增加了查看本部门所有员工的日报、对日报进行批注和回退、导出部门日报为Excel、查看部门日报提交率统计。系统管理端则管理用户账号、部门信息、系统参数比如日报截止时间。所有功能加起来大概十二个菜单项左右这对一个毕设项目的工作量来说是合适的。再多就容易写不完再少就显得内容单薄。权限设计上我用的是最经典的三张表方案用户表、角色表、用户角色关联表。Spring Boot那边写一个拦截器在请求进入Controller之前检查当前登录用户是否拥有目标角色。具体实现就是定义一个Interceptor重写preHandle方法从session里取出登录用户再查一下角色编码。这个方案简单直观答辩时也容易讲清楚——不需要引入Spring Security那套复杂的过滤器链要知道Spring Security的默认登录页和密码加密机制反而会让很多同学在答辩时被问懵。2.2 数据库表设计的关键细节整个项目一共设计了五张核心表用户表、角色表、用户角色关联表、日报表、部门表。下面我把日报表和用户表的结构分享出来这两个表是整个系统的地基。用户表sys_user的核心字段包括id、username、password、real_name、department_id、phone、email、status、create_time。password字段我直接存MD5加密后的值不是明文这虽然是老方案了但在毕设层面足够了。你要是想显得专业一点可以用Spring Security自带的BCryptPasswordEncoder它每次加密的结果都不同更安全答辩时可以提这一点作为亮点。日报表daily_report是业务核心我设计的字段如下字段名类型说明idbigint主键user_idbigint提交人IDreport_datedate日报所属日期work_contenttext今日工作内容work_progressvarchar(500)进度说明problemstext遇到的问题plan_tomorrowtext明日计划report_typetinyint日报类型日报/周报/月报statustinyint0草稿 1待审批 2已通过 3已回退reviewer_idbigint审批人IDreview_commentvarchar(500)审批意见create_timedatetime提交时间update_timedatetime最后修改时间这个表结构有几个细节值得说。第一user_id上一定加索引因为查询某个人某段时间的日报是最频繁的操作没有索引数据量大了之后会慢得离谱。第二status字段我特意设计成0到3四个值而不是简单的0和1。因为实际业务里需要支持先存草稿再提交和审批不过打回重填这两个场景如果只做两态设计后面扩展时会非常痛苦。第三review_comment和reviewer_id我一开始没加是做到审批功能时发现需要记录审批痕迹才补上的。这就是典型的先设计再开发的好处——你提前梳理清楚了就不用频繁改表。2.3 初始数据准备sys_user表不用手动去SQL文件里拼插入语句直接用MyBatis-Plus的代码生成器或者写一个CommandLineRunner启动时初始化即可。我的做法是写一个initDataRunner项目启动时自动检查管理员账号是否存在不存在就创建一个用户名admin、密码admin123MD5加密、角色绑定管理员。这个做法有几个好处第一部署到新环境时不用额外执行SQL第二演示视频录制时直接启动就能登录第三评委看到系统首次启动自动初始化管理员这个设计会给你加分。不过要注意自动创建的管理员密码一定要在项目说明文档中写清楚否则部署者登录不进去会以为系统出Bug了。3. 核心功能实现与代码解析3.1 登录鉴权与用户体系登录功能我摒弃了最基础的Session Cookie做法的直接裸写但也没有引入Spring Security。方案是登录成功后把用户对象写入Session同时生成一个token串存到Cookie里过期时间设为30分钟。拦截器同时校验Session和Cookie的有效性。为什么这么设计完全用Session的话项目重启后所有用户都掉线体验不好。完全用JWT的话又涉及无状态鉴权、token刷新这些概念毕设论文里写起来反而复杂。折中方案既能讲清楚原理又能在演示时做到关闭浏览器再打开仍然保持登录的效果。核心代码不复杂我贴一个登录Controller的骨架PostMapping(/login) public Result login(String username, String password, HttpSession session, HttpServletResponse response) { // 1. 根据用户名查用户 LambdaQueryWrapperSysUser wrapper new LambdaQueryWrapper(); wrapper.eq(SysUser::getUsername, username); SysUser user userService.getOne(wrapper); // 2. 校验密码MD5加密比对 if (user null || !MD5Util.encrypt(password).equals(user.getPassword())) { return Result.error(用户名或密码错误); } // 3. 校验状态 if (user.getStatus() 0) { return Result.error(账号已被禁用); } // 4. 查询角色信息 ListString roles userService.getUserRoles(user.getId()); // 5. 保存登录态 session.setAttribute(loginUser, user); session.setAttribute(loginRoles, roles); String token UUID.randomUUID().toString().replace(-, ); Cookie cookie new Cookie(token, token); cookie.setMaxAge(1800); response.addCookie(cookie); return Result.success(); }有几个小坑我必须提醒。第一密码比对一定要先查用户再比对密码不要写select * from user where username? and password?这种一条SQL完成校验的写法。因为那样你无法区分用户不存在和密码错误而且密码字段会在URL参数或日志中暴露的风险变大。第二Cookie的HttpOnly属性在生产环境要设置为true防止XSS脚本读取到token。第三登录失败的错误信息不要写得太具体统一返回用户名或密码错误防止被别人用来探测用户名是否存在。3.2 日报提交与审批流程日报的提交功能是整个系统最核心的交互点。前端是Layui的form表单提交后端接收字段、校验必填项、设置status为1待审批后插入数据库。业务规则上有一个容易遗漏的点同一天不能重复提交日报。在Controller里加一个校验——查一下当前用户在report_date当天是否已经存在status不为0的记录存在就拒绝提交并提示今日日报已提交。这个规则用LambdaQueryWrapper一条查询就能搞定long count dailyReportService.count( new LambdaQueryWrapperDailyReport() .eq(DailyReport::getUserId, userId) .eq(DailyReport::getReportDate, today) .ne(DailyReport::getStatus, 0) ); if (count 0) { return Result.error(今日日报已提交如需修改请联系主管回退); }这里有个业务设计上的取舍我允许员工在草稿状态下反复修改自己的日报但一旦提交status1员工就不能再改。要修改只能由主管回退status3员工重新编辑后再提交。这个闭环既保证了日报的严肃性又保留了容错空间答辩时讲这个业务规则的设计思路是很加分的。审批功能同样简单主管在待审批列表里看到日报详情后选择通过或回退通过时status置为2回退时status置为3并填写审批意见。注意审批操作需要做权限控制拦截器要校验当前用户角色是主管或管理员。日报的类型字段我加了一个report_type用来区分日报和周报。有的公司周报是单独的表但我这里设计成同一张表用类型字段区分这样可以复用审批逻辑和统计逻辑。如果你要扩展月报同理再给一个枚举值即可。3.3 统计报表的实现思路统计报表是日报管理系统里看起来最厉害的部分也是答辩时评委最容易追问的地方。我用两个维度来展示统计数据个人维度和部门维度。个人维度展示的是日历热力图类似GitHub的贡献图每一天一个格子颜色深浅代表当天是否提交日报以及提交质量评分。这个热力图我用的是纯前端方案后端返回一个月份内每天的提交记录列表前端根据日期映射颜色。整个图标我用的是轻量的ECharts它在Layui页面里引入非常方便一个div加几行配置项就能画出漂亮的图表。部门维度展示的是日报提交率趋势图。SQL上用GROUP BY按日期聚合统计每天应提交人数和实际提交人数SELECT dr.report_date, COUNT(DISTINCT dr.user_id) AS actual_count, (SELECT COUNT(*) FROM sys_user u WHERE u.department_id #{deptId} AND u.status 1) AS total_count FROM daily_report dr WHERE dr.status IN (1, 2) AND dr.report_date BETWEEN #{startDate} AND #{endDate} GROUP BY dr.report_date这条SQL在数据量很少的毕设项目里执行没有任何性能问题。但要注意如果评委追问公司有几千人怎么优化你得答出来可以预计算统计表或者用定时任务每天生成当天的统计快照。我实际项目的做法是后一种——写一个Spring Boot的定时任务Scheduled注解每天凌晨跑一次把昨天的日报统计写入一张daily_report_stats汇总表。查询时直接读汇总表扛不住也不怕。这个设计在论文里可以写成一个系统优化章节非常加分。3.4 Excel导出与文件处理日报导出Excel是我的项目里一个亮点。用的是Apache POI简单场景下直接new一个XSSFWorkbook创建Sheet、Row、Cell逐行写入数据。但如果你需要复用可以封装一个通用Excel导出工具类接收表头和数据集两个参数就生成文件。POI导出和前端配合的方式我建议这样后端生成Excel后写入HttpServletResponse的输出流设置Content-Disposition为attachment文件名用URLEncoder编码。前端就是一个普通的a标签链接直接点击下载不需要AJAX异步处理。这背后有个小知识点如果前端用form表单的action提交导出请求浏览器会直接触发下载如果用AJAX请求返回的二进制流就需要前端手动处理成Blob再触发下载。毕设里用前者简单靠谱。还有一个文件上传的需求日报可能附带图片或文档附件。Spring Boot接收MultipartFile很直接注意设置spring.servlet.multipart.max-file-size为10MBmax-request-size为50MB。上传的文件我会存到服务器的upload目录下数据库只存相对路径。这里一定要强调不要直接把上传的文件名拼接进路径去存储要重命名为UUID文件名防止文件名冲突和路径穿越攻击。4. 项目部署与上线实操4.1 本地开发环境搭建开发环境我推荐三个版本JDK 8Spring Boot 2.7.x默认支持到JDK 17但JDK 8最稳、Maven 3.6.3、MySQL 8.0。IDE用IDEA社区版就够不需要旗舰版的Spring Assistant插件手动创建项目结构完全可以。创建Spring Boot项目的两种方式我都试过。第一种是Spring Initializr网页生成选好依赖后下载ZIP压缩包解压。第二种是用IDEA自带的Spring Initializr在New Project里选Spring Boot 2.7.18依赖勾选Spring Web、MyBatis Framework、MySQL Driver、Thymeleaf、Lombok。这两种方式生成的骨架一致注意Lombok需要安装IDEA插件并且在Maven配置中声明注解处理器。项目配置文件application.yml关键部分如下server: port: 8080 servlet: context-path: / spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/daily_report_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: 123456 thymeleaf: cache: false mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0url里的几个参数是必加的characterEncodingutf8保证中文不乱码serverTimezoneAsia/Shanghai防止日期时间差8小时useSSLfalse避免连接时SSL握手警告。有同学连接数据库报错Public Key Retrieval is not allowed需要在url末尾加allowPublicKeyRetrievaltrue。启动时如果看到数据库表不存在的报错解决方案是提前执行项目目录下的sql/init.sql初始化脚本或者把MyBatis-Plus的自动建表能力打开——但自动建表只能建表不能建索引所以我推荐手动执行SQL脚本更可控。4.2 服务器部署步骤部署目标我选的是阿里云轻量应用服务器2核4G配置、CentOS 7.9系统这对于一个毕设项目来说绰绰有余。整个部署过程可以总结为五步装环境、导数据库、打包、上传、启动。第一步装环境。CentOS上用yum安装JDK 8注意不要用默认的OpenJDK建议下载Oracle JDK的tar包解压到/usr/local/java然后配置/etc/profile里的JAVA_HOME、PATH、CLASSPATH三个环境变量。这个配置网上教程很多我就说一个验证点输入java -version出现java version 1.8.0_xxx而不是openjdk version...就是配置成功。MySQL安装使用宝塔面板最省事在软件商店装MySQL 8.0然后创建数据库daily_report_db再把本地的SQL脚本上传导入。注意宝塔面板的MySQL默认只允许本地访问远程连接需要先在安全组放行3306端口再在MySQL里执行授权命令GRANT ALL PRIVILEGES ON daily_report_db.* TO root% IDENTIFIED BY 密码否则本地Navicat连不上云数据库。第二步到第四步就是常规操作在本地执行mvn clean package -DskipTeststarget目录下生成jar包用scp或宝塔文件管理器上传到服务器的/app/daily-report目录。启动命令我用的是nohup java -jar daily-report.jar --spring.profiles.activeprod \ --server.port8080 /logs/daily-report.log 21 加了nohup和之后关闭SSH窗口服务也不会停。日志重定向到/logs/daily-report.log方便排查问题。第五步配置Nginx反向代理。宝塔面板可以直接添加站点配置反向代理指向127.0.0.1:8080然后开启SSL免费证书用Lets Encrypt。这样部署方可以通过域名或公网IP访问系统浏览器地址栏不会出现端口号。4.3 部署踩坑记录部署过程中我遇到过三个印象深刻的问题写出来让大家避雷。第一个是端口占用。云服务器上如果一个端口被系统的其他服务占了最常见的是8080被某Java程序或Tomcat服务占用Spring Boot启动时直接报Port 8080 was already in use。排查方法是用netstat -tlnp | grep 8080看看哪个进程占着然后杀掉它或者改Spring Boot的端口。第二个是内存配置。如果你默认的JVM参数在2核4G的服务器上跑很容易出现PermGen或堆内存不足。推荐在启动时加上-Xms256m -Xmx512m给系统留足内存。第三个是时区问题。数据库存的日期比实际慢8小时原因是服务器时区不是Asia/Shanghai。处理方法是在启动命令里加上-Duser.timezoneAsia/Shanghai并且在JVM和数据库连接串上都统一时区。4.4 演示视频录制技巧配套的演示视频是整个交付物里容易被忽视但是很加分的一项。录制时不要直接录静态页面的截图滚动而是模拟真实业务场景管理员登录、创建测试员工账号、员工账号提交日报、主管审批、查看统计图表、导出Excel。整个流程控制在10分钟以内太长了评委看不动。视频里特别值得录制的几个点是登录鉴权的拦截效果未登录访问系统页面跳转登录、日报重复提交的校验提示、回退后员工修改日报的流程、统计图表的数据联动。这些都是功能细节评委看到你有意识的把这些边界情况处理好了会认为你真的理解这个系统而不是只会抄代码。录制工具我用的是OBS Studio免费开箱即用输出MP4格式确保分辨率在1920x1080然后压缩到100MB以内方便传输。另外花一分钟配上字幕观感立刻专业很多。5. 常见问题与排查技巧实录5.1 运行报错速查表下面这个表总结了我做这个项目时遇到的高频报错基本覆盖了新手可能碰到的90%的问题。报错信息原因分析解决方案启动报错Port 8080 was already in use端口被占用netstat查找PID并kill或修改server.portjava.sql.SQLException: Access denied for user数据库用户名/密码不对核对application.yml配置信息确认MySQL授权Communications link failureMySQL没启动或连接串错误检查MySQL服务状态确认数据库地址、端口Cannot load driver class: com.mysql.cj.jdbc.Driver缺少MySQL驱动依赖pom.xml引入mysql-connector-j依赖后刷新Maven中文乱码数据库字符集非utf8mb4建库时指定utf8mb4连接url加characterEncodingutf8Whitelabel Error Page404请求路径不存在或Controller未扫描检查类上有没有RestController/Controller注解启动类包结构是否覆盖数据查询为空但数据库有数据字段名驼峰与下划线映射问题开启map-underscore-to-camel-case或SQL中写别名前端页面模板找不到Thymeleaf模板路径错误确认templates目录结构和controller返回逻辑视图名一致5.2 答辩评委最爱追问的几个点毕设答辩时评委问的问题往往不是让你现场写代码而是考察你有没有真的理解项目的关键决策。针对日报管理系统我整理了几个高频追问的应答思路。第一个问题为什么用Spring Boot而不用Spring MVC传统项目回答要点是Spring Boot本质上是Spring MVC的增强封装它通过自动配置减少了大量XML配置内置Tomcat让部署从打WAR包放Tomcat变成直接运行JAR包开发效率更高。同时Spring Boot生态与微服务、云原生天然兼容后续可以平滑升级。第二个问题权限管理是怎么实现的回答要点是RBAC模型用户-角色-权限三层结构系统里只用了角色这一层来控制用户表关联角色表登录后把角色存进Session拦截器通过匹配角色编码决定是否放行。扩展性上如果要精细到菜单按钮级权限可以在角色和菜单之间再增加权限关联表。第三个问题日报提交的高并发场景怎么考虑这个问题有可能被问到因为日报提交通常是集中在每天下班前的那个小时。我的回答策略是当前系统使用MySQL行锁和唯一索引user_id report_date联合唯一索引来保证一个用户一天只能提交一条正式日报避免重复数据。如果未来量大了可以引入Redis做分布式锁或者用消息队列异步削峰。注意联合唯一索引的DDL建法和重复插入时的DuplicateKeyException处理可以在答辩时主动说出来这能体现你对数据一致性的思考。第四个问题系统安全性做了哪些防护这个问题现在越来越常问。我的项目做了五层防护登录接口有简单验证码可选实现、使用了参数化查询防止SQL注入MyBatis-Plus的Wrapper天然就是参数化的、对返回前端的HTML进行了转义处理同时拦截器对静态资源路径做了白名单放行、密码MD5加密存储、上传功能校验了文件扩展名和大小。5.3 代码质量控制与论文素材整理最后聊一下这个项目的代码组织和论文素材。项目结构我采用标准的Maven结构包名用com.example.dailyreport下面分为controller、service、mapper、entity、config、interceptor、util几个包。entity对应数据库表用Lombok的Data注解简化getter/setter。service层写业务逻辑mapper层继承MyBatis-Plus的BaseMappercontroller层只做参数接收和结果返回。三层其实是四层结构清晰区分开。论文的目录结构建议按这个顺序写绪论背景意义、国内外现状、研究内容、相关技术介绍Spring Boot、MyBatis-Plus、MySQL、Thymeleaf、系统分析可行性分析、需求分析、用例图、功能模块图、系统设计总体架构图、功能设计、数据库设计ER图、系统实现每个核心功能配截图和关键代码、系统测试测试用例表、测试结果、总结与展望。写论文时有几个素材我强烈建议你现在就开始积累项目架构图推荐用ProcessOn画别手绘、数据库ER图、功能模块图、核心代码注释截图、测试用例表。这些图在答辩PPT里会直接决定评委的第一印象。我甚至见过一个同学把所有界面截图整理成系统截图18张直接放附录论文看起来内容厚实到不行。我在实际开发中还发现一个实用技巧就是给每个Controller方法加上Swagger注解springfox或springdoc这样论文的接口说明部分可以直接从Swagger UI上截图描述接口的入参和出参这个比你自己画表格直观多了。虽然毕设系统通常不上线Swagger但项目里集成它成本极低论文里又能多两张图何乐而不为。6. 个人实操体会与后续扩展方向整个日报管理系统从零到交付我按每天3-4小时有效开发时间计算大约用了11天。其中数据库设计1天、后端接口5天、前端页面3天、部署调试1天、写论文一周。最花时间的地方不是写代码而是处理各种环境和兼容性问题——Thymeleaf的版本匹配、Layui的表格数据格式、POI导出Excel的单元格样式。我个人实际操作中的体会是毕设项目一定要坚持核心功能跑通优先、边缘功能后续迭代的原则。日报提交、审批、列表、统计这四个核心链路先连起来然后再去加上传、导出、定时任务这些加分项。很多同学一天到晚卡在登录页的验证码显示不出来或者某个CSS样式不对浪费了本该用在核心业务逻辑上的时间。对想把这个项目做得更漂亮的朋友我建议几个后续扩展方向第一引入WebSocket实时通知主管审批通过后员工页面弹出一个消息提醒第二集成ECharts的仪表盘统计页把部门日报提交率、异常状态、趋势曲线汇总到一块大屏上这个做出来视觉效果非常震撼第三用Spring Cache Redis缓存部门统计结果并在论文里写一段缓存优化分析第四引入JWT替代Session给后续前后端分离重构留一个接口。这几个方向任何一个做好了答辩的评级都能上一个台阶。最后再分享一个小技巧交付物中的部署说明文档不要只写步骤一定要把遇到的坑和解决方案也写进去。比如如果启动时报XXX错误请检查XXX配置。这能让部署者很可能是答辩评委或同学在遇到问题时自助解决减少来回沟通也显得你考虑周全。说实话一个部署说明写得清楚的毕设项目和部署说明写得敷衍的项目给评委的印象差别真的很大。