基于Spring、Mybatis、Spring MVC的留言本
实验名称基于Spring、Mybatis、Spring MVC的留言本实验目的和要求 目的熟练掌握Spring、Mybatis、Spring MVC框架基本用法。要求实现简单留言本的发贴和回复功能效果图如下实验实现思路及步骤一、核心实现思路以 SSMSpring、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重定向到列表页。视图层编写留言列表 JSPmessageList.jsp用 JSTL 遍历留言数据展示留言人、时间、内容显示已有回复提供回复表单与发布留言链接编写发布留言 JSPpublishMessage.jsp设计表单收集留言人姓名与内容提供发布与取消按钮。系统测试与运行启动 MySQL 服务与 Tomcat 服务器查看控制台确认无报错访问留言列表页验证初始状态点击发布留言输入信息提交验证留言新增与页面重定向在回复表单输入内容提交验证回复显示通过 MySQL 客户端查询 message 表确认数据存储正确。主要开发工具IntelliJ IDEA2025.1.3MySQL 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-cardhover 时阴影加深shadow-card-hover增强视觉交互如图1-1。图1-1 整体效果2. 核心功能交互效果1发表新留言功能表单设计左侧发帖区包含 “标题”必填、“用户名”必填、“内容”必填三个输入项其中 “内容” 使用多行文本框rows4。提交按钮为蓝色主色调bg-primaryhover 时变为深蓝色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-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 ListReply replies;// 无参/有参构造、getter/setter方法}关键说明配合 MyBatis 的mapUnderscoreToCamelCase配置需在mybatis-config.xml中设置可自动完成字段映射无需手动编写resultMapListReply 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.javapublic interface MessageMapper {ListMessage selectAllMessages(Param(sort) String sort);int insertMessage(Message message);ListMessage searchMessages(Param(keyword) String keyword);}关键说明接口设计原则每个方法对应一个具体的数据库操作方法名与业务语义一致如selectAllMessages即 “查询所有留言”便于后续 Service 层调用Param(sort)注解用于传递单个参数时指定参数名确保 MyBatis 在 XML 映射文件中能通过#{sort}正确获取参数值如sort为 “newest” 时按时间降序“oldest” 时升序返回值设计ListMessage查询操作返回多条留言数据符合 “留言列表展示” 功能需求int新增操作返回 “受影响的行数”MySQL 中新增 1 条数据成功时返回 1失败返回 0用于判断新增是否成功无实现类原因MyBatis 会在运行时通过 “动态代理” 自动生成接口的实现类核心逻辑在对应的 XML 映射文件如MessageMapper.xml中通过 SQL 语句定义减少重复代码。3. Service 层代码MessageServiceImpl.javaServiceTransactionalpublic class MessageServiceImpl implements MessageService {Autowiredprivate MessageMapper messageMapper;Autowiredprivate ReplyMapper replyMapper;Overridepublic ListMessage getAllMessages(String sort) {ListMessage messages messageMapper.selectAllMessages(sort);messages.forEach(msg - {ListReply replies replyMapper.selectByMessageId(msg.getId());msg.setReplies(replies);});return messages;}Overridepublic 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.javaControllerRequestMapping(/message)public class MessageController {Autowiredprivate MessageService messageService;RequestMapping(/list)ResponseBodypublic ListMessage getMessageList(RequestParam String sort) {return messageService.getAllMessages(sort);}RequestMapping(/add)ResponseBodypublic MapString, Object addMessage(Message message) {MapString, Object result new HashMap();int row messageService.addMessage(message);result.put(success, row 0);return result;}}关键说明Controller与RequestMappingController标识类为请求处理器RequestMapping(/message)定义统一路径前缀避免不同 Controller 的路径冲突如其他功能的路径可前缀/userResponseBody注解实验中前端通过 AJAX 异步请求后端需要 JSON 格式的响应数据而非跳转页面该注解会自动将 Java 对象ListMessage或Map转为 JSON无需手动处理格式转换RequestParam String sort接收前端传递的sort参数如前端请求/message/list?sortnewest若前端未传该参数会报错确保请求参数完整性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关联查询、事务管理等关键技能同时发现对复杂查询优化和前端样式细节优化仍需加强。后续可扩展用户登录认证、留言删除编辑、图片上传等功能进一步完善系统。