博客:从零实现一个 Web 留言板 ------ Spring MVC 开发全流程解析
## 一、 场景铺垫:为什么我们需要一个留言板?
在 Web 开发的学习旅程中,如果说"Hello World"是第一步,那么留言板 就是连接前后端的第一个"实战哨所" 。它不仅包含基础的 HTTP 请求与响应,更深入涉及了异步交互(AJAX) 、数据持久化逻辑 以及前后端接口约定 。
想象一下,你正在为学校社团开发一个"表白墙"或"交流角",用户输入想说的话,点击提交,瞬间信息就在下方实时展示 。这背后,Spring MVC 是如何像指挥官一样调度数据的?让我们揭开它的面纱。
## 二、 核心开发链路
### 1. 契约先行:前后端交互接口约定
在开发之前,前端和后端团队必须达成"共识",即接口文档 。针对留言板,我们约定了两个核心服务:
-
获取全部留言 (GET) :
/message/getList。返回 JSON 格式的留言列表 。 -
发表新留言 (POST) :
/message/publish。接收包含"谁"、"对谁说"、"内容"的请求 。
最终我们的项目的大致界面如下:

获取留言接口,需要为我们返回一个类似于留言类型的对象,这个对象中自然包含多个属性, 一般返回的结果中包含两个或者多个参数 我们就要需要来定义一个实体类来对其进行封装, 这里我定义一个MessageInfo的实体类
创建实体类的同时自然也要为其添加设置,获取类属性的一系列方法,即使可能也用不到,但还是需要为其添加
古法编程的方式自然就是手动添加,通过用右键 -> generate来按需选择需要添加的方法

### 2. 效率神器:引入 Lombok 简化开发
尽管我们可以通过ide自动为我们生成其属性对应的get,set等方法,但我们认为这还是太麻烦了这个时候就可以使用Lombok来简化这个添加流程
java
import lombok.*;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MessageInfo {
private String from;
private String to;
private String message;
}
在使用这个插件的前提还要在配置文件中引入对应的依赖,
xml
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version> <scope>provided</scope>
</dependency>
-
@Data 注解 :只需在
MessageInfo类上添加一个注解,Lombok 就会在编译期自动生成 Getter/Setter、toString、equals 等冗长代码 。 -
原理探究 :Lombok 并非在运行时起作用,而是在编译期根据注解修改字节码 。
我们写的java代码会先经过编译转为字节码.class文件,随后jvm再把字节码加载,解析,执行,转为机器码. lombok就是在编译时期起作用的

-
数据存储 :由于尚未引入数据库,我们使用内存集合
List<MessageInfo>来暂存数据 。 -
参数校验 :使用 Spring 提供的
StringUtils.hasLength()严谨地判断留言内容是否为空 。
实体类已创建,首先就是来定义一个类,包含对应的接口来操作留言,同时要注意路径以及注解的定义,这里我简单创建了一个MessageController类
java
package com.amadeus.springbootdemo;
import ch.qos.logback.core.util.StringUtil;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@RequestMapping("/message")
@RestController
public class MessageController {
List<MessageInfo> messageInfoList = new ArrayList<>();
@GetMapping("/getList")
public List<MessageInfo> getInfoList(){
return messageInfoList;
}
@PostMapping("/publish")
public String publish(@RequestBody MessageInfo messageInfo){
//messageInfo任意信息不全.返回OK : 0
if(!StringUtils.hasText(messageInfo.getFrom())
|| !StringUtils.hasText(messageInfo.getTo())
|| !StringUtils.hasText(messageInfo.getMessage())){
return "{/ok/ : 0}";
}
messageInfoList.add(messageInfo);//添加留言信息
return "{/ok/ : 1}";
}
}
由于还未涉及数据库操作,所以我们使用List链表来对于publish操作中提交的留言信息进行存储. 但是由于存储在内存中,服务重启也就会丢失了.
3. 前端交互逻辑(ajax异步)
利用 jQuery 的 AJAX 技术,我们实现了页面的"无刷新更新":
Ajax 最核心的特点就是:**前端跟后端交互,不刷新整个页面,只局部更新内容
试想一下,你正在执行一个登录网站的操作,如果账号密码输入错误,网站并不会直接强制让你跳转到一个新的网页,在这个网页中呈现出"验证码或者账号错误"这样的提示字眼,而是局部更新前端页面,进行信息展示
比如我以力扣为例,在登录失败时也只会更新局部页面

- 点击提交时 (
submit):将输入框数据封装发送,成功后清空输入框并即时渲染新留言 。

- 页面加载时 (
load):自动向后端请求已有留言并动态挂载到 DOM 树上 。
但是如果我们刷新这个前端页面时,会发现留言内容被清空,之前的操作都看不到了,所以为了解决这一问题,就需要后端代码来参与了
为此我们需要依据先前的两个接口来修改部分前端逻辑

## 三、 实操总结
通过留言板案例,我们可以复习以下关键注解 :
-
@RestController :组合了
@Controller和@ResponseBody,表示该类所有方法均返回 JSON 数据而非视图 。 -
@RequestMapping:定义路由映射,将 URL 路径与后端方法绑定 。
-
@RequestBody:用于接收请求正文中的 JSON 数据 。
-
同时也能学习到如何把后端返回Content-Type: text/plain 数据转化为json对象的三种方式,以便于前端进行对象的属性校验,处理逻辑进行界面展示.
## 四、 思考与延伸
在留言板的开发中,我们目前将数据存储在服务器内存 中(如 ArrayList) 。
思考: 一旦重启服务器,现有的留言数据会发生什么?在生产环境中,我们应该如何优化这个设计,才能保证数据的永久可靠?
答案当然是通过数据库,把每次publish提交的留言存在数据库中,做到持久化存储
本文有关留言板的相关开发介绍就到这里了,如有纰漏还请指出~~