实验名称 | 基于Spring、Mybatis、Spring MVC的留言本 | |
实验目的和要求 : | ||
目的:熟练掌握Spring、Mybatis、Spring MVC框架基本用法。 要求:实现简单留言本的发贴和回复功能,效果图如下: | ||
实验实现思路及步骤: | ||
一、核心实现思路 以 SSM(Spring、Spring MVC、MyBatis)框架为技术核心,遵循 MVC 分层架构设计留言本系统。其中,Spring 负责管理 Service 层 Bean 的创建与依赖注入,并提供事务管理保障数据操作一致性;Spring MVC 承担请求处理与视图跳转,通过 Controller 接收前端请求、调用 Service 层逻辑,再将数据传递到视图层渲染;MyBatis 简化数据持久化,借助 Mapper 接口与 XML 映射文件实现留言查询、新增、回复更新,避免硬编码 SQL。整体流程为前端发起请求→Spring MVC 拦截并分发到对应 Controller→Controller 调用 Service 处理业务→Service 调用 Dao 层操作数据库→数据通过 JSP 视图展示,最终实现发布留言、列表展示、管理员回复的完整功能。 二、具体实施步骤 环境搭建与依赖配置:在 IntelliJ IDEA 中创建 Maven Web 项目,设置项目标识;在 pom.xml 中引入 SSM 框架核心依赖、MySQL 驱动、数据库连接池(Druid)、JSP 相关依赖等;配置 Tomcat 9.0 服务器,将项目部署并设置端口与上下文路径。 框架配置文件编写:编写 Spring 配置文件(applicationContext.xml),配置 Service 层扫描、Druid 数据源、MyBatis SqlSessionFactory、Mapper 接口扫描及事务管理;编写 Spring MVC 配置文件(spring-mvc.xml),配置 Controller 层扫描、视图解析器(指定 JSP 路径与后缀)及静态资源放行;编写 MyBatis 配置文件(mybatis-config.xml),配置日志(Log4j)与实体类别名;编写 web.xml,配置 Spring 监听器、Spring MVC 前端控制器(DispatcherServlet)及字符编码过滤器解决中文乱码。 数据库设计与创建:创建 message_db 数据库,在库中新建 message 表,表包含 id(主键自增)、username(留言人)、content(留言内容)、create_time(留言时间,默认当前时间)、reply(回复内容)、reply_time(回复时间)字段;通过 MySQL 客户端执行 SQL 语句完成数据库与表的创建。 分层代码开发: 实体层:创建 Message 类,对应 message 表字段,生成无参、有参构造及 getter/setter 方法。 Dao 层:编写 MessageMapper 接口,定义查询所有留言(按创建时间倒序)、新增留言、更新回复的方法;编写对应的 Mapper XML 映射文件,实现接口方法的 SQL 逻辑。 Service 层:编写 MessageService 接口,定义获取留言列表、发布留言、回复留言的业务方法;编写 Service 实现类,注入 MessageMapper,调用 Dao 层方法处理业务,添加 @Transactional 注解保障事务。 Controller 层:创建 MessageController,添加 @RequestMapping 指定类级请求前缀;编写方法分别处理跳转留言列表页(获取留言数据存入 Model 并返回视图名)、跳转发布留言页(直接返回视图名)、处理发布留言请求(接收表单参数调用 Service,重定向到列表页)、处理回复请求(接收留言 ID 与回复内容调用 Service,重定向到列表页)。 视图层:编写留言列表 JSP(messageList.jsp),用 JSTL 遍历留言数据展示留言人、时间、内容,显示已有回复,提供回复表单与发布留言链接;编写发布留言 JSP(publishMessage.jsp),设计表单收集留言人姓名与内容,提供发布与取消按钮。 系统测试与运行:启动 MySQL 服务与 Tomcat 服务器,查看控制台确认无报错;访问留言列表页验证初始状态;点击发布留言输入信息提交,验证留言新增与页面重定向;在回复表单输入内容提交,验证回复显示;通过 MySQL 客户端查询 message 表,确认数据存储正确。 | ||
主要开发工具 | IntelliJ IDEA2025.1.3,MySQL 8.0,Navicat | |
实验效果及主要实现代码: | ||
一、实验效果说明 1. 整体页面布局与视觉呈现 顶部导航栏:固定在页面顶部(sticky top-0),左侧显示系统名称 “SSM 留言本” 与留言图标(fa fa-comments),右侧包含 “欢迎访问” 提示文本与 “刷新” 按钮。导航栏采用白色背景 + 阴影效果,点击 “刷新” 按钮时会触发页面数据重新加载,同时显示 “页面已刷新” 的 Toast 提示(底部右侧弹出,3 秒后自动消失),提升用户操作反馈感。 核心功能区:采用响应式布局,在 PC 端(lg:flex)分为左右两栏,移动端自动堆叠为纵向排列。左侧占 1/3 宽度,为 “发表新留言” 功能区;右侧占 2/3 宽度,为 “留言列表 + 筛选控制” 功能区,两栏均使用白色卡片式设计(bg-white rounded-lg shadow-card),hover 时阴影加深(shadow-card-hover),增强视觉交互,如图1-1。 图1-1 整体效果 2. 核心功能交互效果 (1)发表新留言功能 表单设计:左侧发帖区包含 “标题”(必填)、“用户名”(必填)、“内容”(必填)三个输入项,其中 “内容” 使用多行文本框(rows="4")。提交按钮为蓝色主色调(bg-primary),hover 时变为深蓝色(bg-blue-600),并带有图标(fa fa-paper-plane),增强操作引导。如图1-2。 图1-2 发表新留言 交互逻辑: 未填写必填项时,浏览器原生校验(required)会提示 “请填写此字段”,避免空数据提交; 填写完成后点击 “发布”,通过 AJAX 异步提交数据(无页面刷新),提交过程中按钮禁用(防止重复提交); 提交成功后:① 表单自动清空;② 留言列表实时刷新,新留言置顶显示,如图1-3。 图1-3 刷新新留言 (2)留言列表展示功能 数据展示格式:每条留言以独立卡片呈现,包含 3 个核心区域: 留言头部:浅蓝色背景(bg-primary bg-opacity-10),左侧显示留言标题(加粗,font-semibold),右侧显示发布时间(浅灰色小字体,text-xs text-gray-dark); 留言内容:白色背景,显示留言正文(text-gray-dark),自动换行适配内容长度; 留言底部:浅灰色背景(bg-gray-light),左侧显示回复数量(如 “回复 (2)”),右侧显示 “回复” 按钮(蓝色文本,hover 时加深); 回复列表:每条留言下方嵌套显示关联的回复,回复项采用浅灰色边框分隔,显示回复内容与回复时间(text-sm字体),无回复时不显示空白区域,避免视觉冗余。 用户提交回复后,模态框自动关闭,列表实时刷新显示新回复,同时弹出操作提示,互动流程顺畅,如图1-4 点击留言底部的 "回复" 按钮,会弹出一个模态框(半透明背景,居中显示),模态框顶部显示 "回复留言" 标题,中间区域显示被回复留言的标题和内容(灰色背景),下方是 "回复内容" 文本框(必填),底部有 "取消" 和 "回复" 按钮。填写回复内容后点击 "回复",前端验证通过后发送请求到后端,成功后关闭模态框,刷新列表显示新回复,并弹出提示如图1-5。 图1-5 刷新回复页面 (3)排序与搜索功能 排序交互:右侧留言列表顶部包含 “排序下拉框”,提供 “最新发布”(默认)与 “最早发布” 两个选项。选择排序方式后,无需页面刷新,留言列表会实时按所选规则重新排列(最新发布按createTime降序,最早发布按createTime升序),排序过程中无加载等待提示(因数据量小,响应速度 < 300ms)。 搜索交互:排序下拉框右侧为 “搜索输入框”(带fa fa-search图标),输入关键词(支持标题、留言内容、回复内容匹配)时,实时筛选留言列表,如图1-6 图1-6 搜索留言 二、核心代码实现 1. 实体层代码 // Message实体类 public class Message { private Integer id; private String title; private String username; private String content; private Date createTime; private List<Reply> replies; // 无参/有参构造、getter/setter方法 } 关键说明: 配合 MyBatis 的mapUnderscoreToCamelCase配置(需在mybatis-config.xml中设置),可自动完成字段映射,无需手动编写resultMap; List<Reply> replies是核心关联字段:因实验需实现 “留言 - 回复” 功能,1 条留言可对应多条回复,用List存储关联的回复数据,为 Service 层 “查询留言时同步查回复” 提供数据结构; 无参构造、getter/setter 是 MyBatis 反射赋值的必要条件(MyBatis 通过反射创建对象并设置字段值)。 // Reply实体类 public class Reply { private Integer id; private Integer messageId; private String content; private Date createTime; // 无参/有参构造、getter/setter方法 } 关键说明: messageId是外键字段:通过该字段与message表的id关联,确保每条回复能对应到具体留言,是 “查询留言时同步查回复” 的关联依据; 字段设计极简:仅保留回复功能必需的核心信息,符合实验 “简单留言本” 的需求,避免冗余字段增加开发复杂度。 2. Dao 层代码(MessageMapper.java) public interface MessageMapper { List<Message> selectAllMessages(@Param("sort") String sort); int insertMessage(Message message); List<Message> searchMessages(@Param("keyword") String keyword); } 关键说明: 接口设计原则:每个方法对应一个具体的数据库操作,方法名与业务语义一致(如selectAllMessages即 “查询所有留言”),便于后续 Service 层调用; @Param("sort")注解:用于传递单个参数时指定参数名,确保 MyBatis 在 XML 映射文件中能通过#{sort}正确获取参数值(如sort为 “newest” 时按时间降序,“oldest” 时升序); 返回值设计: List<Message>:查询操作返回多条留言数据,符合 “留言列表展示” 功能需求; int:新增操作返回 “受影响的行数”(MySQL 中新增 1 条数据成功时返回 1,失败返回 0),用于判断新增是否成功; 无实现类原因:MyBatis 会在运行时通过 “动态代理” 自动生成接口的实现类,核心逻辑在对应的 XML 映射文件(如MessageMapper.xml)中通过 SQL 语句定义,减少重复代码。 3. Service 层代码(MessageServiceImpl.java) @Service @Transactional public class MessageServiceImpl implements MessageService { @Autowired private MessageMapper messageMapper; @Autowired private ReplyMapper replyMapper; @Override public List<Message> getAllMessages(String sort) { List<Message> messages = messageMapper.selectAllMessages(sort); messages.forEach(msg -> { List<Reply> replies = replyMapper.selectByMessageId(msg.getId()); msg.setReplies(replies); }); return messages; } @Override public int addMessage(Message message) { message.setCreateTime(new Date()); return messageMapper.insertMessage(message); } } 关键说明: @Service注解:将类标识为 “业务层 Bean”,Spring 启动时会扫描该类并创建实例存入 IOC 容器,后续 Controller 层可通过@Autowired直接注入使用(解耦 “业务逻辑” 与 “请求处理”); @Autowired注解:实现 “依赖注入”(Spring 核心特性),自动从 IOC 容器中获取MessageMapper和ReplyMapper的实例,无需手动创建,避免代码耦合(如无需写messageMapper = new MessageMapperImpl()); @Transactional注解:实验中 “新增留言” 是简单操作,但若后续扩展 “新增留言后同步记录日志” 等多步数据库操作,该注解可确保所有操作要么同时成功,要么同时失败(如日志插入失败时,留言新增也回滚),保障数据一致性; 业务逻辑封装:getAllMessages中 “循环查回复” 的逻辑封装在 Service 层,Controller 层调用时无需关注 “如何关联回复”,只需直接获取完整数据,符合 “单一职责原则”(Controller 只处理请求,Service 只处理业务)。 4. Controller 层代码(MessageController.java) @Controller @RequestMapping("/message") public class MessageController { @Autowired private MessageService messageService; @RequestMapping("/list") @ResponseBody public List<Message> getMessageList(@RequestParam String sort) { return messageService.getAllMessages(sort); } @RequestMapping("/add") @ResponseBody public Map<String, Object> addMessage(Message message) { Map<String, Object> result = new HashMap<>(); int row = messageService.addMessage(message); result.put("success", row > 0); return result; } } 关键说明: @Controller与@RequestMapping:@Controller标识类为请求处理器,@RequestMapping("/message")定义统一路径前缀,避免不同 Controller 的路径冲突(如其他功能的路径可前缀/user); @ResponseBody注解:实验中前端通过 AJAX 异步请求后端,需要 JSON 格式的响应数据(而非跳转页面),该注解会自动将 Java 对象(List<Message>或Map)转为 JSON,无需手动处理格式转换; @RequestParam String sort:接收前端传递的sort参数(如前端请求/message/list?sort=newest),若前端未传该参数会报错,确保请求参数完整性; Message message参数:Spring MVC 自动将前端提交的表单参数(如title=测试&username=张三)封装为Message对象,参数名与Message字段名一致即可自动匹配(如title对应message.setTitle()),简化参数接收代码; Map返回结果:前端需要知道 “新增是否成功”,用Map存储success键(布尔值),前端可通过data.success直接判断(如if(data.success){提示成功}),符合前后端交互的通用逻辑。 5. 前端 AJAX 交互代码 // 发布留言提交 postForm.addEventListener('submit', function(e) { e.preventDefault(); const title = document.getElementById('postTitle').value; const username = document.getElementById('postUsername').value; const content = document.getElementById('postContent').value; fetch('/message/add', { method: 'POST', headers: {'Content-Type': 'application/x-www-form-urlencoded'}, body: `title=${encodeURIComponent(title)}&username=${encodeURIComponent(username)}&content=${encodeURIComponent(content)}` }) .then(res => res.json()) .then(data => { if (data.success) { postForm.reset(); handleRefresh(); showToast('留言发布成功!'); } }); }); e.preventDefault():表单默认提交会刷新页面,破坏 “无刷新交互” 的体验,该方法阻止默认行为,确保 AJAX 异步提交; 请求路径/message/add:必须与 Controller 层MessageController的@RequestMapping("/message")+@RequestMapping("/add")完全一致,否则后端无法接收请求; method: 'POST':新增操作需修改数据库数据,用 POST 请求更安全(GET 请求参数会暴露在 URL 中),与后端 Controller 的请求方式适配; Content-Type: application/x-www-form-urlencoded:告知后端 “请求体是表单参数格式”,与 Controller 中 “Message message接收参数” 的方式匹配,确保后端能正确解析参数; encodeURIComponent():处理用户输入中的中文(如姓名 “张三”),避免中文在传输过程中出现乱码,后端 Spring MVC 会自动解码; 响应处理逻辑: res.json():将后端返回的 JSON 字符串转为 JavaScript 对象(与@ResponseBody的 JSON 格式对应); data.success:直接获取后端返回的success字段(来自 Controller 的Map),判断新增是否成功; 成功后的操作:reset()清空表单(方便用户继续发布)、handleRefresh()刷新留言列表(实时显示新留言)、showToast()提示成功(告知用户操作结果),形成完整的交互闭环。 | ||
遇到的问题和解决方法: | ||
问题:前端 AJAX 提交数据后,后端无法接收中文参数。 解决方法:在 web.xml 配置 CharacterEncodingFilter,设置编码为 UTF-8,确保前后端编码一致。 问题:前端提交留言后,页面需要刷新才能显示新数据。 解决方法:使用 AJAX 异步提交表单,成功后通过 JavaScript 动态添加留言到页面顶部,无需整体刷新。 | ||
实验总结: | ||
本次实验通过SSM框架完整实现了留言本的发帖、回复、排序、搜索等功能,深入掌握了三大框架的整合与应用。Spring的依赖注入简化了组件间的耦合,Spring MVC实现了请求的灵活分发与异步数据返回,MyBatis高效完成数据持久化操作,配合Tailwind CSS构建的前端页面,提升了系统的交互体验与视觉效果。实验中掌握了AJAX异步交互、MyBatis关联查询、事务管理等关键技能,同时发现对复杂查询优化和前端样式细节优化仍需加强。后续可扩展用户登录认证、留言删除编辑、图片上传等功能,进一步完善系统。 | ||
基于Spring、Mybatis、Spring MVC的留言本
张小明
前端开发工程师
Cocos2d-x 3.17.2 在Win10上还能战吗?一份给怀旧项目维护者的环境搭建与迁移指南
Cocos2d-x 3.17.2 在Win10上的生存指南:老项目维护者的实战手册 当Unity和Unreal Engine用华丽的粒子特效吸引眼球时,仍有不少项目默默坚守在Cocos2d-x 3.17.2的战场上。这不是技术保守,而是现实选择——那些运行了五年以上的手游代码库、特定…
88.乐理基础-记号篇-反复记号(二)D.C.、D.S.、Fine、Coda:从标记到实战演奏的完整导航
1. 反复记号:乐谱中的导航系统 第一次看到乐谱上那些D.C.、D.S.、Fine、Coda标记时,我完全摸不着头脑。就像开车时看到陌生的路标,明明知道它们很重要,却不知道具体含义。后来我才明白,这些反复记号其实就是乐谱的导航…
5分钟快速上手:Blender终极PSK/PSA格式导入导出插件完整指南
5分钟快速上手:Blender终极PSK/PSA格式导入导出插件完整指南 【免费下载链接】io_scene_psk_psa A Blender extension for importing and exporting Unreal PSK and PSA files 项目地址: https://gitcode.com/gh_mirrors/io/io_scene_psk_psa Unreal PSK/PSA…
DS4Windows完整指南:3步让PlayStation手柄在Windows电脑上完美运行
DS4Windows完整指南:3步让PlayStation手柄在Windows电脑上完美运行 【免费下载链接】DS4Windows Like those other ds4tools, but sexier 项目地址: https://gitcode.com/gh_mirrors/ds/DS4Windows 想要在Windows电脑上使用PlayStation手柄畅玩所有游戏吗&am…
公交线网规划问题(Transit route network design problem, TRNDP)最新精确算法,EJOR收录
我的最新论文针对经典NP-hard问题,首次提出了两个ILP模型和精确算法。在领域最常用的Mandls network数据集上,该算法实现了高效获得最优解,在精确算法效率方面处于领先地位。TRNDP和VRP在一定程度上很相似,都是需要构建线路让车来…
Windows HEIC缩略图提供程序:深入解析系统级图像预览技术
Windows HEIC缩略图提供程序:深入解析系统级图像预览技术 【免费下载链接】windows-heic-thumbnails Enable Windows Explorer to display thumbnails for HEIC/HEIF files 项目地址: https://gitcode.com/gh_mirrors/wi/windows-heic-thumbnails 超过80%的i…