基于SpringBoot+jQuery實(shí)現(xiàn)留言板功能
本教程將手把手教你使用 Spring Boot 3.x 作為后端 + jQuery 作為前端交互,實(shí)現(xiàn)一個(gè)簡(jiǎn)潔美觀的留言板系統(tǒng)。功能包括:
- 查看所有留言(分頁(yè)可選)
- 提交新留言(姓名 + 內(nèi)容)
- 實(shí)時(shí)刷新顯示最新留言
- 基本的表單校驗(yàn)
技術(shù)棧:Spring Boot(后端 REST API) + Thymeleaf(可選) + jQuery(Ajax 交互) + Bootstrap(美化)
項(xiàng)目結(jié)構(gòu)概覽
messageboard ├── src │ ├── main │ │ ├── java/com/example/messageboard │ │ │ ├── MessageboardApplication.java │ │ │ ├── entity/Message.java │ │ │ ├── repository/MessageRepository.java │ │ │ └── controller/MessageController.java │ │ └── resources │ │ ├── static/css/style.css │ │ ├── static/js/main.js │ │ └── templates/index.html │ └── ... └── pom.xml
步驟 1:創(chuàng)建 Spring Boot 項(xiàng)目
使用 https://start.spring.io/ 生成項(xiàng)目,添加依賴:
- Spring Web
- Spring Data JPA
- H2 Database(嵌入式數(shù)據(jù)庫(kù),方便測(cè)試)
- Thymeleaf(模板引擎)
- Lombok(簡(jiǎn)化代碼)
步驟 2:實(shí)體類與數(shù)據(jù)庫(kù)配置
Message.java
package com.example.messageboard.entity;
import jakarta.persistence.*;
import lombok.Data;
import java.time.LocalDateTime;
@Entity
@Data
public class Message {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@Column(columnDefinition = "TEXT")
private String content;
private LocalDateTime createTime = LocalDateTime.now();
}
application.yml(resources 下)
spring:
datasource:
url: jdbc:h2:mem:messageboard
driver-class-name: org.h2.Driver
username: sa
password:
h2:
console:
enabled: true # 訪問(wèn) http://localhost:8080/h2-console 查看數(shù)據(jù)
jpa:
hibernate:
ddl-auto: update
show-sql: true
步驟 3:Repository 接口
package com.example.messageboard.repository;
import com.example.messageboard.entity.Message;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import java.util.List;
public interface MessageRepository extends JpaRepository<Message, Long> {
@Query("SELECT m FROM Message m ORDER BY m.createTime DESC")
List<Message> findAllOrderByCreateTimeDesc();
}
步驟 4:Controller 實(shí)現(xiàn) REST API
package com.example.messageboard.controller;
import com.example.messageboard.entity.Message;
import com.example.messageboard.repository.MessageRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Controller
public class MessageController {
@Autowired
private MessageRepository messageRepository;
// 主頁(yè)(返回 Thymeleaf 模板)
@GetMapping("/")
public String index(Model model) {
return "index"; // 返回 templates/index.html
}
// 獲取所有留言(按時(shí)間倒序)
@GetMapping("/api/messages")
@ResponseBody
public List<Message> getMessages() {
return messageRepository.findAllOrderByCreateTimeDesc();
}
// 提交新留言
@PostMapping("/api/messages")
@ResponseBody
public ResponseEntity<?> addMessage(@RequestBody Message message) {
if (message.getName() == null || message.getName().trim().isEmpty() ||
message.getContent() == null || message.getContent().trim().isEmpty()) {
return ResponseEntity.badRequest().body("姓名和內(nèi)容不能為空!");
}
messageRepository.save(message);
return ResponseEntity.ok(message);
}
}
步驟 5:前端頁(yè)面(index.html)
放在 src/main/resources/templates/index.html
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>留言板</title>
<link rel="external nofollow" rel="stylesheet">
<link rel="stylesheet" th:href="@{/css/style.css}" rel="external nofollow" >
</head>
<body class="bg-light">
<div class="container py-5">
<div class="row">
<div class="col-lg-8 mx-auto">
<div class="card shadow">
<div class="card-header bg-primary text-white">
<h3 class="mb-0">留言板</h3>
</div>
<div class="card-body">
<!-- 留言表單 -->
<form id="messageForm">
<div class="mb-3">
<label class="form-label">姓名</label>
<input type="text" class="form-control" id="name" required>
</div>
<div class="mb-3">
<label class="form-label">留言內(nèi)容</label>
<textarea class="form-control" id="content" rows="4" required></textarea>
</div>
<button type="submit" class="btn btn-primary">提交留言</button>
</form>
<hr>
<!-- 留言列表 -->
<h5 class="mt-4">所有留言</h5>
<div id="messageList" class="mt-3">
<!-- jQuery 動(dòng)態(tài)加載 -->
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/jquery@3.7.1/dist/jquery.min.js"></script>
<script th:src="@{/js/main.js}"></script>
</body>
</html>
步驟 6:jQuery 實(shí)現(xiàn)前后端交互(main.js)
放在 src/main/resources/static/js/main.js
$(document).ready(function () {
// 頁(yè)面加載時(shí)獲取留言
loadMessages();
// 提交表單
$('#messageForm').submit(function (e) {
e.preventDefault();
const name = $('#name').val().trim();
const content = $('#content').val().trim();
if (!name || !content) {
alert('姓名和內(nèi)容不能為空!');
return;
}
$.ajax({
url: '/api/messages',
type: 'POST',
contentType: 'application/json',
data: JSON.stringify({name: name, content: content}),
success: function (newMessage) {
$('#name').val('');
$('#content').val('');
// 新留言插入到最頂部
prependMessage(newMessage);
alert('留言成功!');
},
error: function () {
alert('提交失敗,請(qǐng)重試');
}
});
});
// 加載所有留言
function loadMessages() {
$.get('/api/messages', function (messages) {
$('#messageList').empty();
messages.forEach(message => {
appendMessage(message);
});
});
}
// 添加一條留言到列表
function appendMessage(message) {
const time = new Date(message.createTime).toLocaleString();
const html = `
<div class="border rounded p-3 mb-3 bg-white">
<div class="d-flex justify-content-between">
<strong>${escapeHtml(message.name)}</strong>
<small class="text-muted">${time}</small>
</div>
<p class="mt-2 mb-0">${escapeHtml(message.content)}</p>
</div>
`;
$('#messageList').append(html);
}
// 新留言插入頂部
function prependMessage(message) {
const time = new Date(message.createTime).toLocaleString();
const html = `
<div class="border rounded p-3 mb-3 bg-white animate__animated animate__fadeIn">
<div class="d-flex justify-content-between">
<strong>${escapeHtml(message.name)}</strong>
<small class="text-muted">${time}</small>
</div>
<p class="mt-2 mb-0">${escapeHtml(message.content)}</p>
</div>
`;
$('#messageList').prepend(html);
}
// 防止 XSS 攻擊
function escapeHtml(text) {
return $('<div>').text(text).html();
}
// 可選:每10秒自動(dòng)刷新
// setInterval(loadMessages, 10000);
});
步驟 7:可選美化樣式(style.css)
body {
min-height: 100vh;
}
.animate__fadeIn {
animation: fadeIn 0.5s;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
運(yùn)行與測(cè)試
- 啟動(dòng)項(xiàng)目 → 訪問(wèn) http://localhost:8080
- 輸入姓名和內(nèi)容 → 點(diǎn)擊提交
- 新留言實(shí)時(shí)顯示在頂部
- 刷新頁(yè)面數(shù)據(jù)持久(H2 內(nèi)存數(shù)據(jù)庫(kù),重啟會(huì)丟失,可換 MySQL)
擴(kuò)展建議
- 換成 MySQL 持久化存儲(chǔ)
- 添加分頁(yè)(Pageable)
- 支持回復(fù)、刪除(需登錄)
- 使用 Vue/React 替換 jQuery
- 添加驗(yàn)證碼防刷
這個(gè)留言板項(xiàng)目簡(jiǎn)單優(yōu)雅,非常適合初學(xué)者練習(xí) Spring Boot + 前端 Ajax 交互!
到此這篇關(guān)于基于SpringBoot+jQuery實(shí)現(xiàn)留言板功能的文章就介紹到這了,更多相關(guān)SpringBoot jQuery 留言板內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot2.X Kotlin系列之?dāng)?shù)據(jù)校驗(yàn)和異常處理詳解
這篇文章主要介紹了SpringBoot 2.X Kotlin系列之?dāng)?shù)據(jù)校驗(yàn)和異常處理詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-04-04
SpringSecurity Oauth2訪問(wèn)令牌續(xù)期問(wèn)題
這篇文章主要介紹了SpringSecurity Oauth2訪問(wèn)令牌續(xù)期問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-04-04
Java及數(shù)據(jù)庫(kù)對(duì)日期進(jìn)行格式化方式
這篇文章主要介紹了Java及數(shù)據(jù)庫(kù)對(duì)日期進(jìn)行格式化方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
深入解析Java的Servlet過(guò)濾器的原理及其應(yīng)用
這篇文章主要介紹了深入解析Java的Servlet過(guò)濾器的原理及應(yīng)用,Java編寫的Servlet通常是一個(gè)與網(wǎng)頁(yè)一起作用于瀏覽器客戶端的程序,需要的朋友可以參考下2016-01-01
Spring?Boot?消息隊(duì)列與異步處理的應(yīng)用小結(jié)
這篇文章給大家介紹了Spring?Boot?消息隊(duì)列與異步處理的應(yīng)用小結(jié),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2026-04-04
Feign遠(yuǎn)程調(diào)用參數(shù)里面內(nèi)容丟失的解決方案
這篇文章主要介紹了Feign遠(yuǎn)程調(diào)用參數(shù)里面內(nèi)容丟失的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03
Java實(shí)現(xiàn)Markdown轉(zhuǎn)為PDF的兩種方式
文章介紹了兩種將Markdown轉(zhuǎn)換為PDF的方法:一是使用商業(yè)授權(quán)的Spire.Doc框架,操作簡(jiǎn)單但需要授權(quán);二是使用開源的Markdown到HTML再到PDF的轉(zhuǎn)換流程,需要自行實(shí)現(xiàn)轉(zhuǎn)換邏輯,需要的朋友可以參考下2026-01-01

